Have a *nix sh script put itself into the background
Posted by Alec The Geek on 24 February 2011
In the Unix Bourne style shell languages (e.g. sh, bash, ksh etc) you can put a long running command (or another script) into the background so that control returns to the user. The original idea is that you can perform other work whilst the background process continues. This is achieved by adding a &, for example $ myVeryLongRunningCommand and options >/tmp/myOutput &.
It would be nice to be able to have scripts place themselves in the background, when appropriate, without the user having to worry about and I assumed there would be a “shell’ish” way to do that — however I couldn’t find anything so I knocked something up in a hurry. I put it here for future generations and in the hope that improvements will be suggested.
#! /bin/sh if [[ "$_myBackGround" != "_backGroundFlag" ]]; then nohup /bin/sh -c "_myBackGround=_backGroundFlag; export _myBackGround;$0 $*" > /tmp/$0.$$.stdout 2> /tmp/$0.$$.stderr & echo $0 passed to background with arguments "$*". NB stderr is /tmp/$0.$$.stderr and stdout is /tmp/$0.$$.stdout exit fi # Your script goes here e.g. echo hello: My arguments are $0 $* echo Hello -- this is an error >&2
2 Responses to “Have a *nix sh script put itself into the background”
Sorry, the comment form is closed at this time.

![[FSF Associate Member]](http://static.fsf.org/nosvn/associate/fsf-10505.png)
Justin "Uni" Griggs said
Hullo there sir, it’s about a year after you posted this and I stumbled upon it.
I used your basic principle of the script being a self contained wrapper but improved upon it a bit to give it some more daemon-esque features, like a PID file and “safe” execution (i.e. if the script is already running the attempt to rerun it should throw an error, or in exceptional circumstances, try to correct itself.)
For future generations, here is the code itself:
http://pastebin.com/TkyJb50R WARNING: some of the language in the daemon section is a bit…colorful.
The code relevant to the daemonization itself:
#
# Stage 4 Variables
#
# Required to identify this script from other instances
ID=$$;
# Location of the PID file.
PID=/var/run/statusled.pid;
# Easy reference to null device.
NULL=/dev/null;
# Processing string to seek out the statusled processes
LOOKUP=$(ps aux | grep -e statusled.sh | grep -v ${ID}\
| grep -v grep | awk ‘{print $2}’);
#
# Stage 4 Functions – Daemonize (Safely)
#
# First if loop checks if the file exists
# Yes it does:
# Second if loop checks if the PID is alive
# Yes it is:
# Exit with “I’m already Running.”
# No it is not:
# Third if loop checks if -A- statusled process is running
# Yes there is:
# The PID in the file is wrong, update it.
# No there is not:
# The process was killed, restart and write pid to file.
# No it does not:
# Second if loop checks if -A- statusled process is running
# Yes there is:
# Our PID file got deleted, recreate it.
# No there is not:
# Our Daemon was probably never started, start it.
#
# This is accomplished through a lot of nasty variable matching. The grep -o
# line that follows the initial match line exists because for some reason bash
# will fork this script into about 3 processes. We can find the first two, but
# I was never able to use the special variables to pull up the third, so that
# line uses this fork to our advantage, and scans the PID tree for any PIDs
# that are also contained inside the PID file (from our first look up) and when
# a match is found, it returns it. The basic principle depends on the kernel
# not assigning us the same PID twice.
#
if [ -a /var/run/statusled.pid ]; then
if ps -p $(cat ${PID}) > ${NULL}; then
echo “StatusLED: I’m already running.”;
else
if ps -p ${LOOKUP} > ${NULL};
then
echo “StatusLED: I’m already running, but my PID number is wrong. Fixing…”
echo ${LOOKUP} > ${PID};
cat ${PID} | grep -o $(ps -p ${LOOKUP} | awk ‘{ print $1 }’\
| sed ‘s/[^0-9]*//g’) > ${PID};
else
STATUS_LED &
echo $! > ${PID}
fi
fi
else
if ps -p ${LOOKUP} > ${NULL};
then
echo “StatusLED: I’m already running, but my PID file is missing. Fixing…”
echo ${LOOKUP} > ${PID};
cat ${PID} | grep -o $(ps -p ${LOOKUP} | awk ‘{ print $1 }’\
| sed ‘s/[^0-9]*//g’) > ${PID};
else
STATUS_LED &
echo $! > ${PID};
fi
fi
# EOF
Alec The Geek said
Cool — thank you for sharing