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.

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