Subjectively

dd if=/dev/random | kirk > blog

Subjectively header image 2

OS/X daemon script template

November 9th, 2009 · No Comments · Linux, OS X

This is a daemon script written for OS/X in bash. It can be run either as a daemon or a launchd service. The launchd service file will follow in a later post.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/bin/bash
 
# put these lines in the file header comment
#          FILE:  |FILENAME|
#         USAGE:  ./|FILENAME| start [ stop | restart ] [ --nofork ] [ --debug ]
 
#-----------------------------------------------------------------------
#Uncomment the following line to echo all commands to the terminal
#-----------------------------------------------------------------------
#set -x
# better yet, set the --debug command line flag and syslog it.
 
#===  FUNCTION  ================================================================
#          NAME:  cleanup
#   DESCRIPTION:  post service processing (clean temp space,pid files)
#    PARAMETERS:  none
#       RETURNS:  none
#===============================================================================
function cleanup () {
  echo "trap exit"
  #Don't recurse in the exit trap
  trap - INT TERM EXIT
  #remove the pid file cleanly on exit
  [[ -f "$pidfile" ]] && rm "$pidfile"
  #add other post processing cleanup here
  exit
}
 
#===  FUNCTION  ================================================================
#          NAME:  isrunning
#   DESCRIPTION:  is any previous instance of this script already running
#    PARAMETERS:  pidfile location
#       RETURNS:  boolean
#===============================================================================
function isrunning() {
  pidfile="$1"
  [[ ! -f "$pidfile" ]] && return 1  #pid file is nonexistent
  procpid=$(<"$pidfile")
  [[ -z "$procpid" ]] && return 1  #pid file contains no pid
  # check process list for pid existence and is an instance of this script
  [[ ! $(ps -p $procpid | grep $(basename $0)) == "" ]] && value=0 || value=1
  return $value
}
 
#===  FUNCTION  ================================================================
#          NAME:  createpidfile
#   DESCRIPTION:  atomic creation of pid file with no race condition
#    PARAMETERS:  the pid to put in the file, the filename to use as a lock
#       RETURNS:  none
#===============================================================================
function createpidfile() {
  mypid=$1
  pidfile=$2
  #Close stderr, don't overwrite existing file, shove my pid in the lock file.
  $(exec 2>&-; set -o noclobber; echo "$mypid" > "$pidfile") 
  [[ ! -f "$pidfile" ]] && exit #Lock file creation failed
  procpid=$(<"$pidfile")
  [[ $mypid -ne $procpid ]] && {
    #I'm not the pid in the lock file
    # Is the process pid in the lockfile still running?
    isrunning "$pidfile" || {
      # No.  Kill the pidfile and relaunch ourselves properly.
      rm "$pidfile"
      $0 $@ &
    }
    exit
  }
  #  I win!  set a trap for the lockfile on exit
}
 
 
#-----------------------------------------------------------------------
#  Check number of command line arguments
#-----------------------------------------------------------------------
[[ $# -lt 1 ]] || [[ $# -gt 3 ]] && {
  echo -e "\tUsage:  ${0##/*/} start [ | stop | restart ] [ --nofork ] [ --debug ]"
  exit 1
  }
 
#A launchd script in OSX is not supposed to fork
nofork=`echo "$*" | grep "\-\-nofork"`
[[ ! -z $nofork ]] >> nofork=true
[[ -z $nofork ]] >> nofork=false
#check to send everything to syslog
debug=`echo "$*" | grep "\-\-debug"`
[[ ! -z $debug ]] >> debug=true
[[ -z $debug ]] >> debug=false
 
#configuration
basename="`basename $0 .sh`"
# look for the conf file in the same folder as the script
conf="$(dirname $(which $0))/${basename}.conf" #<-- which handles "bash -x $0 start"
[[ -f "$conf" ]] && source "$conf"
 
#===  FUNCTION  ================================================================
#          NAME:  pidfilename
#   DESCRIPTION:  create a predictable pid file name, put it in the right inode
#    PARAMETERS:  none
#       RETURNS:  path and filename
#===============================================================================
function pidfilename() {
  myfile=$(basename "$0" .sh)
  whoiam=$(whoami)
  mypidfile=/tmp/$myfile.pid
  [[ "$whoiam" == 'root' ]] && mypidfile=/var/run/$myfile.pid
  echo $mypidfile
}
 
pidfile=$(pidfilename)
 
#find the temp directory 
tempfile=$(mktemp -t j) 
#put all of your incidentals in the tempdir 
tempdir=$(dirname $tempfile) 
rm $tempfile 
#Do all further processing from the root 
cd / 
# Load the daemon template for OSX 
. /etc/rc.common 
#traps trap 'source $conf' 1  
# response to kill -s HUP $$ should be to read the config file. 
#trap 'echo trap  0; rm -f "$pidfile"; exit'  0     #can't trap this, daemon will exit when parent dies. 
#trap 'cleanup'  3 15     #clean up the pidfile 
#===  FUNCTION  ================================================================ 
#          NAME:  main 
#   DESCRIPTION:  Allows daemon to be run in background 
#    PARAMETERS:  none 
#       RETURNS:  void 
#=============================================================================== 
function main() { 
#         Put your service code here 
while : # Loop forever 
do
   sleep 10
   echo $RANDOM
done 
} 
#===  FUNCTION  ================================================================ 
#          NAME:  StartService 
#   DESCRIPTION:  implements function from /etc/rc.common 
#    PARAMETERS:  none 
#       RETURNS:  void 
#=============================================================================== 
StartService () {   
 
  CheckForNetwork   
 
  isrunning "$pidfile" && {
         echo "$basename is already running"
         exit 1
   }
 
   # do the service
   #   no fork method for launchd service   
  [[ "$nofork" == "true" ]] && {
       #pid file with this process id
      createpidfile $$ "$pidfile"
      trap 'cleanup' INT TERM EXIT
      [[ "$debug" == "true" ]] && trap 'logger -t $0 -i -- $USER : $BASH_COMMAND' DEBUG #syslog everything if we're debugging 
      trap 'logger -t $0 -i -- $USER : $BASH_COMMAND' ERR  #log errors regardless 
      #echo $$ > $pidfile
      main
      exit
  }
 
  [[ "$debug" == "true" ]] && trap 'logger -t $0 -i -- $USER : $BASH_COMMAND' DEBUG #syslog everything if we're debugging 
  trap 'logger -t $0 -i -- $USER : $BASH_COMMAND' ERR  #log errors regardless 
  # fork and exit
  main &
  # create a pid file with the pid of the child
  #  the parent will go away and leave the child owned by init
  createpidfile $! "$pidfile"
  trap 'cleanup' INT TERM 
# #echo $! > $pidfile
 
}
 
#===  FUNCTION  ================================================================
#          NAME:  StopService
#   DESCRIPTION:  implements the function from /etc/rc.common
#    PARAMETERS:  none
#       RETURNS:  void
#===============================================================================
StopService ()
{
 
  [[ -f "$pidfile" ]] && {
    kill $(head -n 1 "$pidfile")
    rm "$pidfile"
  }
  #touch "$quit"
}
 
#===  FUNCTION  ================================================================
#          NAME:  RestartService
#   DESCRIPTION:  implements the function from /etc/rc.common
#    PARAMETERS:  none
#       RETURNS:  void
#===============================================================================
RestartService ()
{
  StopService
  StartService
}
 
#-------------------------------------------------------------------------------
#  Call the function declared in /etc/rc.common to daemonize process
#-------------------------------------------------------------------------------
RunService "$1"  #First parameter is start/stop/restart

Tags:

No Comments so far ↓

There are no comments yet...Kick things off by filling out the form below.

Leave a Comment

You must log in to post a comment.