Linux: How to make your scripts re-read their configuration while running
Assume the following scenario, you have create a script that processes files.. your script is half way processing 1.000.000 files.. but you…
Assume the following scenario, you have create a script that processes files.. your script is half way processing 1.000.000 files.. but you need to do a small change, an sleep value between processing the files.. a really small change.. but we also dont want to stop our time consuming file processing task which is half-done.. well! we are lucky! there is a way and is super easy!.
Lets talk about signals first
In Linux (and other Unix like OSes) signals is a way to inform a process for a particular event, they are software interrupts that delivered to the process by the operating system to indicate that a particular event or condition needs attention.
Some very common signals that you have probably use are
- SIGINT:
ctrl+cinterrupt a running process from keyboard. - SIGKILL: kills the process immediately, cannot be caught, blocked or ignored,
kill -9 <PID> - SIGHUP: Often used to indicate to the process that needs to re-read its configuration,
kill -HUP <PID>
SIGHUP is the signal that we caught and act upon in our script!
The script!
In the bellow example we will create a script and a configuration file, the script will read its configuration file when starts and i will show you what to add to the script to re-reload the configuration while running without interrupting the script execution
Save the following file as config.cfg
sleep_value=2Save the following file as myscript.sh
#!/bin/bash
read_config() {
echo "Reading configuration."
source ./config.cfg
}
trap 'read_config' SIGHUP
read_config
counter=0
while true; do
counter=$((counter+1))
echo "Processing file ${counter} .."
echo "Sleeping for ${sleep_value} seconds."
sleep $sleep_value
doneProvide the script execution rights with chmod
chmod +x ./myscript.shTesting the script
Running the script will give an output like this
Reading configuration.
Processing file 1 ..
Sleeping for 2 seconds.
Processing file 2 ..
Sleeping for 2 seconds.
Processing file 3 ..
Sleeping for 2 seconds.
Processing file 4 ..Now from another terminal window and without killing the process modify config.cfg file sleep_value=10
sleep_value=2Save the file and in the same terminal find with PID of the script with the following command, in my case the PID is 2544, in your case will be something else since PIDs assigned by the OS
ps aux | grep -i myscript.sh | grep -v grep | tr -s " " | cut -d " " -f2
2544Now lets ask from the process to re-read its configuration
kill -HUP 2544Now lets go back to the terminal of the running script, we can nottice two things
- The sleep value has now become 10.
- The counter of the processed files has not been reset, instead continue increasing where is left since reload.
Processing file 121 ..
Sleeping for 2 seconds.
Processing file 122 ..
Sleeping for 2 seconds.
Reading configuration.
Processing file 123 ..
Sleeping for 10 seconds.
Processing file 124 ..
Sleeping for 10 seconds.
Processing file 125 ..Explaining the magic in the script!
Awesome! now we have a script that can re-read its configuration while running and not interrupting the script execution! lets explain how this works!
All this magic in the script takes place because of the trap command, trap is configured to execute a specific function upon the event of a specific signal, in our case we have configure trap to execute read_config function in case of a SIGHUP (the signal that indicates to the process to re-read its configuration)
trap 'read_config' SIGHUPThe read_config function is very simple it just asks bash to use source to load the variables from file config.cfg , note that source isnt limited only to variables but it can also used to load functions and make them available to the main script.
source ./config.cfgConclusion
Knowing how to make your script to re-read its configuration file while running is essential when you want to make your scripts robust and smart!, happy coding! :)