Controlling shell processes using signals

Slashdot it! Delicious Share on Facebook Tweet! Digg!

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
Figure 2: Using a signal, you can control the result of a script by defining a new variable value, as in this example.

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 .

Figure 3: With the help of a couple of simple tools, you can program a clock in the shell in the style of a C64.

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.

Figure 4: You can control the clock for the shell using a simple menu.

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.

Figure 5: The Htop console tool also works with signals, allowing you to control processes.

Buy this article as PDF

Express-Checkout as PDF

Pages: 4

Price $0.99
(incl. VAT)

Buy Ubuntu User

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content