Looping Shell Script Recipe
The following procedure creates and executes a looping script that executes a command with output to a file and a sleep in between each execution:
- If you're using SELinux security, then you'll have to place the
script into an allowed location. First, check SELinux status:
Example output:sestatus | grep "Current mode"
$ sestatus | grep "Current mode" Current mode: enforcing
- If the
sestatus
command does not exist orCurrent mode
is set to anything other thanenforcing
, then you can place the new script anywhere; for example:cd /tmp/
- If SELinux is set to
enforcing
, then place the new script into an allowed directory (may requireroot
permission); for example, a common such directory:cd /usr/local/bin/
- If the
- Create a file named
diagscript.sh
replacing the command after theCHANGEME
comment, and, if necessary, the sleep time and the output location instead of/tmp/
:#!/bin/sh set -e # Change output directory if needed outputfile="/tmp/diag_$(hostname)_$(date +"%Y%m%d_%H%M%S").txt" while true; do echo "[$(date)] Executing iteration" >> "${outputfile}" 2>&1 # CHANGEME: Change the `ps -elfyww` command to your desired command (but make sure to still write to ${outputfile}): ps -elfyww >> "${outputfile}" 2>&1 # Change the sleep time (in seconds) as needed: sleep 30 done
- Manually confirm the looped command exists and works (as some
distributions support different flags). Using the example command above:
ps -elfyww
- Make the script executable:
chmod +x diagscript.sh
- If SELinux is set to
enforcing
, change the security context of the script based on a well-known executable; for example:chcon --reference=/usr/bin/cat diagscript.sh
- Check if you're running in a
systemd
environment:systemctl status
- If
systemctl status
succeeds (running in asystemd
environment), start the script withsystemd-run
so that it's not interrupted if the user that started the script logs out:
Example output:systemd-run ./diagscript.sh
Confirm the script is running by runningRunning as unit: run-r973b3f9d949b4d60a6b9a5fc842b84d1.service; invocation ID: 800d52ff3cb541659df667804ae7b149
systemctl status
on the dynamically generated unit name and confirm it'sactive (running)
; for example:# systemctl status run-r973b3f9d949b4d60a6b9a5fc842b84d1.service [...] Active: active (running) since Tue 2025-01-14 08:41:28 CST; 54s ago Main PID: 2686 (diagscript.sh)
- If
systemctl
does not exist (not running in asystemd
environment), start the script withnohup
so that it's not interrupted if the user that started the script logs out and send it to the background with&
:nohup ./diagscript.sh &
- If
- If you'd like to watch the script output, you may
tail
it (replacing/tmp/
if you used a different directory):tail -f /tmp/diag*txt
- Monitor that the script output does not exhaust disk
- When you are ready to stop the script:
- If the script was started with
systemd-run
, stop it using the dynamically generated service name printed when starting it (or search insystemctl status
output); for example:systemctl stop run-r973b3f9d949b4d60a6b9a5fc842b84d1.service
- If the script was started with
nohup
, kill it by finding the process ID:
Alternatively, if available, usekill ${PID}
pkill
with the script name:pkill -f diagscript.sh
- If the script was started with
- Upload
diag*txt
and any other relevant logs