Linux Box Admin
Trusted Remote Administration
logo

Tilde
What's new
Articles
Micro HowTos
About
Contact



Fresh Micros




A Bourne Again Daemon
(2 votes)
Thursday, 20 April 2006
  A Bourne Again Daemon
exclusive content published on April 20, 2006

In Unix-like systems, a daemon is a process that runs in the background, usually providing some kind of service. Most daemons can be identified in the process list because their names end in d. Examples are the Apache web server (httpd) and the OpenSSH server (sshd). Another thing daemons usually have in common is that they are written in the C programming language. To create a daemon quickly, you can throw one together using the Bourne Again Shell (Bash) scripting language.

More about daemons

There are a couple of other common daemon characteristics. They often have a configuration file with a name ending in ".conf". You can tell a daemon to read its configuration file again by sending it signal HUP (1). Lastly, daemons usually listen on a particular TCP or UDP port for incoming network connections. The network functionality is the only feature we won't duplicate using Bash. It is possible to add a network aware program to a Bash daemon, but that is left as an exercise for the reader.

Please allow me to introduce myself

Here is the basic structure of a Bash daemon:

#!/bin/bash
# This is a simple daemon shell script.
#
# Traps:
# signal HUP (1) read config file again
# signal QUIT (3) delete temp files
# signal TERM (15) delete temp files

conf=/tmp/bashdaemon.conf
source $conf
tempfile=/tmp/BASHDAEMON_$$
touch $tempfile

# set traps
trap 'source $conf' 1
trap 'rm -f $tempfile; exit' 0
trap 'rm -f $tempfile; exit' 3
trap 'rm -f $tempfile; exit' 15

# loop forever
while :
do
    echo $foo
    echo $bar
    sleep 30
done
I saved this script as bashdaemon.sh and made it executable with:
chmod a+x bashdaemon.sh

The bashdaemon.conf file contains variable assignments for two variables, foo and bar. It starts out like this:

foo=famine
bar=death

Let's walk through the script line by line.

conf=/tmp/bashdaemon.conf

This line defines the configuration file, called /tmp/bashdaemon.conf. In the example, all files are in the /tmp directory, but if you want to follow daemon convention, you could put it in /etc.

source $conf

The source built-in command reads and executes the configuration file, activating the variable assignments.

tempfile=/tmp/BASHDAEMON_$$
touch $tempfile


The tempfile serves two purposes. It can be used as work area and it stores the process ID of the daemon in the file name. For example, if the process ID was 1234, the tempfile name would be /tmp/BASHDAEMON_1234. As long as the daemon is running, the tempfile will exist. It gets automatically deleted when the daemon ends (unless it is killed with signal KILL (9)).

trap 'source $conf' 1

This trap allows the daemon to capture signal HUP (1) and tells it to source the configuration file again and continue running. If the variable assignments have been changed, the new values take effect.

trap 'rm -f $tempfile; exit' 0
trap 'rm -f $tempfile; exit' 3
trap 'rm -f $tempfile; exit' 15

These lines trap signals 0, 3, and 15 to delete the tempfile, then exit. See below for more about traps.

while :
do
    echo $foo
    echo $bar
    sleep 30
done
The loop uses a never ending while statement to run until it is ended with one of the signals that tell it to exit or signal 9, killing it unconditionally. Inside the loop, the daemon does its work. In the example, it just prints the contents of the foo and bar variables, then goes to sleep for 30 seconds.

Traps

For those not familiar with traps, a few more words are in order. If you already know about traps, skip ahead. Linux (and Unix) defines a set of messages called signals that can be sent to a program to tell it what to do. The "kill" program is used to send signals from the command line. To view the complete list of signals, try:

kill -l

That is an EL, not the numeral one. For example, the hang up signal (HUP) is signal 1 and the QUIT signal is signal 3. When a program receives the QUIT signal, it exits immediately, unless the program is written to recognize that signal and take other action. Intercepting a signal is called a trap. Most languages have a trap function and in Bash, it is the trap built-in function. The one signal that can't be trapped is KILL -- signal 9. The Bash man page has more details.

Firing it up

There are many ways to run a Bash daemon, depending on how formal you want to get. The least formal way is to start it from a terminal session with the background operator:

./bashdaemon.sh &

This starts the daemon in the background and works, but requires the terminal session to remain open. Another option is to start it from a screen session. Screen is a program that lets you detach a process from the terminal and reattach to it later, even from a different computer. If you haven't tried screen before, it is a powerful tool worth learning. After launching the daemon from screen, you can simply detach, close the terminal, and check on it later as needed.

The most formal option is to set up a run control script like the big daemons use in /etc/rc.d/init.d/. You could even list it in /etc/inittab to have init restart it automatically if it ever failed. On the other hand, if you need to go to these lengths, you probably need to write it in a more appropriate language. Bash daemons excel at quick and dirty solutions.

Killing it softly

To test the signal HUP trap, I started the Bash daemon in the background, then changed the variable assignments in the bashdaemon.conf file. After my edits, the bashdaemon.conf file looked like this:

foo=pestilence
bar=war
Next, I found the process ID of the daemon (1927) by looking at the tempfile name in /tmp. Then, I sent signal 1 to it using:

kill -s HUP 1927

After it received the signal, it started printing the new values from bashdaemon.conf. To kill it for good, I pulled the daemon back into the foreground with fg and used Ctrl-C to end it. Afterward, the tempfile was gone as expected.

Daemons for work and play

Some interesting near real-time stuff can be done with Bash daemons. You could monitor a database, be notified when a certain user logs in, take action when a file is accessed, when a program is run, or anything you dream up. Summon your own daemons to do your bidding.

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 License.
 

Copyright © 2006,2007 Linux Box Admin.

 
My NHL fan blog