This is an ultra simple example bash script, that is also a Daemon
This is probably the simplest Linux Daemon you'll ever see, the whole thing
written in Bash the Bourne Again SHell scripting language, weighing in at
a mere 9 lines of Bash code. OK what makes
a Daemon a Daemon, or put another way, how do Daemons differ
from other programs. The main difference is that once you start
a Daemon it detaches from the terminal that started it. After
the Daemon is running you can logout and the Daemon keeps running without
any user to own it. The kind of programming you do as the author of
a Daemon is considerably different from normal user interactive programs,
remember the first thing you do is detach from the terminal that starts it,
without any console to provide I/O functionality the resulting strategies
available to you tend to be things that monitor, and react to, various events
the system can sense and or take corrective action for.
The thing that started me off in this direction, this time, was for some
inexplicable reason, perhaps some radio interference in the WiFi band was
causing my wireless interface to shutdown. Oh it could be restarted
easily enough, if you were at a local console of that machine,
but if you weren't there, you had to go to that machine, and restart the
wireless. I wrote a bash script in which I invested half
an hour, that periodically examined points in
the /proc directory for signs that the
wireless had given up, and then it would restart it. The trouble is
that it used up an open root terminal just to deal with this.
I looked through my books, I scoured the internet, one guy said
something about a method using a bash builtin
called disown and some example code in
the Bash Cookbook on O'Reilly Press, unfortunately not a book I happen
to have, there was one other example that was Posix compliant, but it seemed
way too complicated for such a simple program. So I started striking
out on my own, playing around with the bash
builtin disown I ended up
with Seconds a very
simple Daemon that bumps up the value by one, in a file once a second,
allowing you to examine it periodically to convince yourself it is indeed
working/or not. From this humble beginning it should be trivial
to make it work with the wireless gimmick I already have.
Interpreting an excerpt of the Bash Man Page:
A running Bash shell exits by default upon receipt of a SIGHUP.
Before exiting however, an interactive shell resends the SIGHUP to all jobs,
whither they're running or stopped. Stopped jobs are first sent
a SIGCONT to ensure that they receive the SIGHUP. To prevent the
shell from killing our Daemon as it exits, due to the pervasive way in which
signals control everything, sparing the sending of a SIGHUP signal to
a particular job, our Daemon for instance, is a simple matter of insuring
that it has been removed from the table of active jobs by using the
Bash disown builtin function.
We in effect tell the shell program to forget it ever launched, what up
to that point was a normal program. Once the shell has forgotten
this important detail, if you run
the jobs program, you will find the Daemon
is nolonger listed, if you exit the bash shell, that is you log out, if you
log back in again you will find that your little program has been working
in your absents.
A word of caution, since most Daemons tend to require root privileges,
if a decision can be somehow fed by an attacker, all of the old
worries come into play, things like privilege escalation, active memory
diversion to permit a function with root privilege to be used by an
attacker for arbitrary code execution. While all very cloak and dagger,
you probably aren't going to
write a simple Daemon that gets a very wide distribution, and such a Daemon
won't gather much of an audience of attackers interested in writing time
consuming malware, that evades poor defenses you might not have created if
you'd had considerably more knowledge about how your attacker gets in.
Remember this is about as far away from a Monoculture as you're ever going
to get, usually it's a one of a kind solution.
Now the example code:
You are expected to write your own strategy, I assume that like me
many a coder is used to writing "normal" code, but like me never
delved into writing Daemons, well here's yer' chance, go fer it!
#! /bin/bash
# To Start Seconds & disown `cat /home/jim/Seconds.pid` #
# To Stop kill -9 `cat /home/jim/Seconds.pid` #
# The executable bash script is rwxr--r-- /home/jim/scripts/Seconds #
# Don't forget to set your execution path environment variable $PATH to #
# include the scripts directory as follows... PATH=$PATH:$HOME/scripts #
# you could even add such a line to your ~/.bash_profile to make this #
# directive automatic upon loging on. #
# #
echo $$ > /home/jim/Seconds.pid
itr=0
while [ true ]
do
itr=$[1+$itr]
echo $itr > /home/jim/Seconds
sleep 1
done
#! /bin/bash # # # To Start Keep_awake Daemon # # Keep_awake & sleep 1 ; disown `cat /root/scripts/Keep_awake.pid` # # # # Note: The above sleep 1 will allow the .pid file write to finish, # # this avoids a nasty "disown before pid file is available" race condition # # # # Warning: # # Do NOT alter this script without taking into account the effects it will # # have on the bootstrap process. /etc/rc.local calls this file to start # # to start wireless running. # # # # To Stop Keep_awake Daemon # # kill -9 `cat /root/scripts/Keep_awake.pid` # # # # This executable bash script is rwx------ /root/scripts/Keep_awake # # Don't forget to set your execution path environment variable $PATH to # # include the scripts directory as follows... PATH=$PATH:$HOME/scripts # # you could even add such a line to your ~/.bash_profile to make this # # directive automatic upon loging on. # # # /bin/echo $$ > /root/scripts/Keep_awake.pid restrt_cnt=0 # Init ReStart logging count # Enter Main Loop (an endless loop) that continuously checks / restores WiFi while [ true ] do { /bin/sleep 20 air=`/usr/bin/tail -n 1 /proc/net/wireless | /usr/bin/cut -b 14-32 | tr -d .` air1=`/bin/echo $air | /usr/bin/cut -d " " -f 1-1` air2=`/bin/echo $air | /usr/bin/cut -d " " -f 2-2` air3=`/bin/echo $air | /usr/bin/cut -d " " -f 3-3` if [ "$[$air1+$air2+$air3]" -eq "0" ] # If wireless is down... then # ...then restore it. { restrt_cnt=$[$restrt_cnt + 1] /bin/echo $restrt_cnt > /root/scripts/Keep_awake.log /sbin/iwconfig wlan0 mode Managed essid shenanigan channel 6 /sbin/ifconfig wlan0 10.0.1.28 netmask 255.255.255.0 broadcast 10.0.1.255 up /bin/echo -e -n "search localhost\nnameserver 10.0.1.20\n" > /etc/resolv.conf # Lay in the Gateway route if, and only if, its missing if [ -z "`/sbin/route -n | /usr/bin/tail -n 1 | /bin/grep "[.-.0-9]\{7,15\} \{2,11\}[.-.0-9]\{7,15\} \{2,11\}[.-.0-9]\{7,15\} \{2,11\}UG \{2,11\}[0-9]\{1,1\} \{2,11\}[0-9]\{1,1\} \{2,11\}[0-9]\{1,1\} \{1,11\}wlan0"`" ] then { /sbin/route add -net 0.0.0.0 netmask 0.0.0.0 gw 10.0.1.30 dev wlan0 } fi } fi } done