Controlling shell processes using signals
|
Intercepting Signals
There is really no way of capturing, blocking, or ignoring the SIGKILL and SIGSTOP signal with a trap. However, you can use all the other signals in shell scripts to elicit another response. You can do this using the trap '<response>' <signals> command in a shell script.
The trap '' 2 line ignores the signal. Without an option or a response, the command undefines almost all signals at the end of the shell script. Signal 10 essentially halts the script in Listing 2 with the output [2]+ User-defined signal 1 ./message.sh . The trap -l command lists the usable signals.
Listing 2
ignoresignals.sh
#! /bin/sh trap while true; do clear echo $0 $$ sleep 1 done
A trap opens up many possibilities. It allows some scripts to delete temporary files when unintentionally logging off the shell. You can also prevent stopping a script through pilot error by having it ignore signals. Conversely, you can use this technique to enter into a running script without needing to restart it.
Listing 3 (reaction.sh ) shows you how you can do this using a function. In the example, the script defines a variable and then displays it. Figure 2 shows the result.
Listing 3
reaction.sh
#! /bin/sh a="Default" # Define function signaltrap() { echo -n "Enter new value: ";read a if [ -z "$a" ]; then echo "No entry -> Abort!" exit fi continue exit 0 } # Trap signal 2 ([Crl]+[C]) trap 'signaltrap' 2 while true; do echo "$$: $a" sleep 3 done
Because of the continue after the loop, the script continues with the given variable value. Another shell sends the kill -2 signal. The terminal with the application accepts the input and the script continues. Another Ctrl+C and an empty input terminate the program.
A Clock for the Shell
You can find a program much prettier than the first attempt at a self-written script. For example, take a look at a retro clock, complete with sound output in the style of a C64 classic home computer (Figure 3). To make it work, you need two programs: figlet and beep .
Once you've installed the tools, the scripts in Listing 4 (clockmenu.sh ) and Listing 5 (clock.sh ) let you experiment further. To begin, start clock.sh , which creates behind a file named .clock.pid that contains the PID. Then, call clockmenu.sh , which extracts the number of the other process from the file. Now you can control the clock.
Listing 4
clockmenu.sh
#! /bin/sh # Get clock time process ID clockpid=$(cat .clock.pid) while true; do clear echo "Control of shell clock" echo " " echo "(l) Local time" echo "(u) UTC" echo "(w) Set alarm" echo "(e) Stop alarm" echo "(E) End control" echo " " echo -n "Select function: ";read f if [ "$f" = "E" ]; then exit elif [ "$f" = "e" ]; then kill -15 $clockpid elif [ "$f" = "w" ]; then echo -n "Enter wake-up time (null for delete): ";read wt echo "$wt" > .clock.wt kill -1 $clockpid elif [ "$f" = "l" ]; then kill -10 $clockpid elif [ "$f" = "u" ]; then kill -12 $clockpid fi done
Listing 5
clock.sh
#! /bin/bash # Ignore signals 2 and 20 trap '' 2 20 # Print process ID for controlling "clockmenu.sh" echo $$ > .clock.pid # Define empty variable for wake-up time $wt wt="" # Set time zone: local time lt="l" # Get wake-up time, or null if [ -e .clock.wt ]; then wt=$(cat .clock.wt) else touch .clock.wt fi # Main loop while true; do # Assign action to signals -- important: # for loop continuation, # don't forget continue! trap 'wt=$(cat .clock.wt); continue' 1 trap 'lt="l"; continue' 10 trap 'lt="u"; continue' 12 # Get times time=$(date +%H:%M:%S) utc=$(date -u +%H:%M:%S) shorttime=$(date +%H:%M) date=$(date +%A\ %d.%m.%Y) week=$(date +%V) hourchime=$(date +%I) quarterhourchime=$(date +%M) # Progess bar seconds: # For loop can't handle "08" or "09". # Therefore, seconds first stored in $a and for # $seconds and cast to computer bc for 0. a=$(date +%S) seconds=$(echo $a -0 | bc) clear # Display time if [ "$lt" = "l" ]; then figlet -f banner $time tzone="Local time" elif [ "$lt" = "u" ]; then figlet -h banner $utc tzone="UTC" fi # Display additional data echo " " echo "Set wake-up time: $wt" echo "$date : $week. Calendar week Timezone: $tzone" echo "----------------------------------------------------------------" # Second hand for((i=0; i<$seconds; i++)); do echo -n "#" done # Chime if [ "$quarterhourchime" != "$alarm" ]; then if [ $quarterhourchime -eq 15 ]; then beep -f 800 elif [ $quarterhourchime -eq 30 ]; then beep -f 800 -r 2 -l 500 -d 500 elif [ $quarterhourchime -eq 45 ]; then beep -f 800 -r 3 -l 500 -d 500 elif [ $quarterhourchime -eq 0 ]; then beep -f 800 -r 4 -l 500 -d 500 beep -f 700 -r $hourchime -l 500 -d 600 fi alarm=$quarterhourchime fi # Alarm if [ "$shorttime" = "$wt" ]; then if [ "$wt" != "$wakeupalarm" ]; then for (( i=1; i <= 5; i++ )); do beep -f 1000 -n -f 2000 -n -f 1500 -n -f 500 -n -f 300 -n -f 3000 done wakeupalarm=$wt fi fi sleep 1 done # Cleanup rm .clock.pid
Figure 4 shows the clock menu that, although rather Spartan, performs all the required functions. Setting the alarm time is done by entering it in the SS:MM format.
Thanks to the figlet tool, the clock appears in a large display. If you set an alarm, the script displays it. The alarm sound will turn off by itself, and the sound is unmistakable. With beep , you can conjure up different sounds from the computer.
The same is true for the hour chime. As with a classic clock, the quarter hour chimes are in a higher tone and the hour chimes are in a lower one. The hour chimes are divided into two 12-hour periods, and you can enter world time (UTC) or local time. Entering e in clockmenu.sh stops the clock.
Note that stopping and restarting the controlling software (i.e., clockmenu.sh ) is necessary after restarting the clock or the signals get sent to the wrong or non-existent process. The sounds that beep creates are generally emitted by the PC's speaker.
You can also use Htop to control the clock, as well as other processes shown in this article. In Figure 5, you can see how Htop is used to kill the reaction.sh script.
« Previous 1 2 3 Next »
Buy this article as PDF
Pages: 4
(incl. VAT)