Created
April 19, 2014 07:22
-
-
Save shawnrice/11076762 to your computer and use it in GitHub Desktop.
A template to write a quick daemon as a bash script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# This is a skeleton of a bash daemon. To use for yourself, just set the | |
# daemonName variable and then enter in the commands to run in the doCommands | |
# function. Modify the variables just below to fit your preference. | |
daemonName="DAEMON-NAME" | |
pidDir="." | |
pidFile="$pidDir/$daemonName.pid" | |
pidFile="$daemonName.pid" | |
logDir="." | |
# To use a dated log file. | |
# logFile="$logDir/$daemonName-"`date +"%Y-%m-%d"`".log" | |
# To use a regular log file. | |
logFile="$logDir/$daemonName.log" | |
# Log maxsize in KB | |
logMaxSize=1024 # 1mb | |
runInterval=60 # In seconds | |
doCommands() { | |
# This is where you put all the commands for the daemon. | |
echo "Running commands." | |
} | |
################################################################################ | |
# Below is the skeleton functionality of the daemon. | |
################################################################################ | |
myPid=`echo $$` | |
setupDaemon() { | |
# Make sure that the directories work. | |
if [ ! -d "$pidDir" ]; then | |
mkdir "$pidDir" | |
fi | |
if [ ! -d "$logDir" ]; then | |
mkdir "$logDir" | |
fi | |
if [ ! -f "$logFile" ]; then | |
touch "$logFile" | |
else | |
# Check to see if we need to rotate the logs. | |
size=$((`ls -l "$logFile" | cut -d " " -f 8`/1024)) | |
if [[ $size -gt $logMaxSize ]]; then | |
mv $logFile "$logFile.old" | |
touch "$logFile" | |
fi | |
fi | |
} | |
startDaemon() { | |
# Start the daemon. | |
setupDaemon # Make sure the directories are there. | |
if [[ `checkDaemon` = 1 ]]; then | |
echo " * \033[31;5;148mError\033[39m: $daemonName is already running." | |
exit 1 | |
fi | |
echo " * Starting $daemonName with PID: $myPid." | |
echo "$myPid" > "$pidFile" | |
log '*** '`date +"%Y-%m-%d"`": Starting up $daemonName." | |
# Start the loop. | |
loop | |
} | |
stopDaemon() { | |
# Stop the daemon. | |
if [[ `checkDaemon` -eq 0 ]]; then | |
echo " * \033[31;5;148mError\033[39m: $daemonName is not running." | |
exit 1 | |
fi | |
echo " * Stopping $daemonName" | |
log '*** '`date +"%Y-%m-%d"`": $daemonName stopped." | |
if [[ ! -z `cat $pidFile` ]]; then | |
kill -9 `cat "$pidFile"` &> /dev/null | |
fi | |
} | |
statusDaemon() { | |
# Query and return whether the daemon is running. | |
if [[ `checkDaemon` -eq 1 ]]; then | |
echo " * $daemonName is running." | |
else | |
echo " * $daemonName isn't running." | |
fi | |
exit 0 | |
} | |
restartDaemon() { | |
# Restart the daemon. | |
if [[ `checkDaemon` = 0 ]]; then | |
# Can't restart it if it isn't running. | |
echo "$daemonName isn't running." | |
exit 1 | |
fi | |
stopDaemon | |
startDaemon | |
} | |
checkDaemon() { | |
# Check to see if the daemon is running. | |
# This is a different function than statusDaemon | |
# so that we can use it other functions. | |
if [ -z "$oldPid" ]; then | |
return 0 | |
elif [[ `ps aux | grep "$oldPid" | grep -v grep` > /dev/null ]]; then | |
if [ -f "$pidFile" ]; then | |
if [[ `cat "$pidFile"` = "$oldPid" ]]; then | |
# Daemon is running. | |
# echo 1 | |
return 1 | |
else | |
# Daemon isn't running. | |
return 0 | |
fi | |
fi | |
elif [[ `ps aux | grep "$daemonName" | grep -v grep | grep -v "$myPid" | grep -v "0:00.00"` > /dev/null ]]; then | |
# Daemon is running but without the correct PID. Restart it. | |
log '*** '`date +"%Y-%m-%d"`": $daemonName running with invalid PID; restarting." | |
restartDaemon | |
return 1 | |
else | |
# Daemon not running. | |
return 0 | |
fi | |
return 1 | |
} | |
loop() { | |
# This is the loop. | |
now=`date +%s` | |
if [ -z $last ]; then | |
last=`date +%s` | |
fi | |
# Do everything you need the daemon to do. | |
doCommands | |
# Check to see how long we actually need to sleep for. If we want this to run | |
# once a minute and it's taken more than a minute, then we should just run it | |
# anyway. | |
last=`date +%s` | |
# Set the sleep interval | |
if [[ ! $((now-last+runInterval+1)) -lt $((runInterval)) ]]; then | |
sleep $((now-last+runInterval)) | |
fi | |
# Startover | |
loop | |
} | |
log() { | |
# Generic log function. | |
echo "$1" >> "$logFile" | |
} | |
################################################################################ | |
# Parse the command. | |
################################################################################ | |
if [ -f "$pidFile" ]; then | |
oldPid=`cat "$pidFile"` | |
fi | |
checkDaemon | |
case "$1" in | |
start) | |
startDaemon | |
;; | |
stop) | |
stopDaemon | |
;; | |
status) | |
statusDaemon | |
;; | |
restart) | |
restartDaemon | |
;; | |
*) | |
echo "\033[31;5;148mError\033[39m: usage $0 { start | stop | restart | status }" | |
exit 1 | |
esac | |
exit 0 |
Some of the content got messed up. like echo "\033[31;5;148mError\033[39m: usage $0 { start | stop | restart | status }"
The original at https://github.com/shawnrice/alfred-cron/blob/master/alfred-cron.sh isn't messed up for anyone looking.
This is a nice idea, but it doesn't work for arbitrarily long-running tasks because of the recursion.
The recursive loop will segfault after some time. Better do a regular infinite loop inside the loop function.
For anyone wanting to get around the broken echo
formatting, you can add an -e
flag to the echo
command to get it to print the formatted output:
echo -e "\033[31;5;148mError\033[0m: usage $0 { start | stop | restart | status }"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks / Nice!
On Ubuntu systems
/bin/sh
points todash
. Dash complains about the double-brackets tests. One way to fix this, is to make sure the script starts with#!/bin/bash
to make sure the bash shell is used....also, line 11 should be removed.