Subjectively

dd if=/dev/random | kirk > blog

Subjectively header image 1

launchd script for OS/X for bash daemon

November 19th, 2009 · Linux, OS X

This is the promised launchd script to run the service in an earlier post.

The name of this file is /Library/LaunchDaemons/com.{domain_name}.{service_name}.plist

Replace any text in curly braces {} with some appropriate information for your script.

When you are finished creating the file, load it with:

 
launchctl load -w /Library/LaunchDaemons/com.{domain_name}.{service_name}.plist

It should crank right up and start doing its’ thang.

Here’s the content of the .plist file:

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Enabled</key>
	<true/>
	<key>GroupName</key>
	<string>staff</string>
	<key>KeepAlive</key>
	<true/>
	<key>Label</key>
	<string>com.{domain_name}.{service_name}</string>
	<key>Program</key>
	<string>/usr/local/bin/{script_name}</string>
	<key>ProgramArguments</key>
	<array>
		<string>{script_name}</string>
		<string>start</string>
		<string>--nofork</string>
	</array>
	<key>QueueDirectories</key>
	<array/>
	<key>RunAtLoad</key>
	<true/>
	<key>ServiceDescription</key>
	<string>Some creative description of your service.</string>
	<key>UserName</key>
	<string>{user_name}</string>
	<key>WatchPaths</key>
	<array/>
</dict>
</plist>

→ No CommentsTags:

OS/X daemon script template

November 9th, 2009 · 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
#!/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.
 
#-----------------------------------------------------------------------
#  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"
whoiam=`whoami` 
# create a pid file with the pid of the process on the first line 
pidfile="/tmp/${basename}.pid" 
[[ $whoiam == 'root' ]] && pidfile="/var/run/${basename}.pid"  
#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 'echo trap  3; rm -f "$pidfile"; exit'  3 15     #clean up the pidfile 
[[ "$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 
#===  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   
[[ -f $pidfile ]] && {
     pid=`head -n 1 $pidfile`
     procname=`ps awx | awk "\\\$1 == $pid { print \\\$7 }"`
     [[ ! -z $procname ]] && [[ "$procname" == "$0" ]] && {
         echo "$basename is already running"
         exit 1
     }
     rm $pidfile
   }
   # do the service
   #   no fork method for launchd service   
[[ "$nofork" == "true" ]] && {
       #pid file with this process id
       echo $$ > $pidfile
      main
      exit
  }
 
  # 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
  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

→ No CommentsTags:

bash shell script to manage pid file creation/deletion

October 30th, 2009 · Linux, OS X

Problem: You want your script to execute without overlapping another execution.
Solution: Make a flag file so you know that your script is already executing.
Extended problem: What if your script dies and leaves the flag file behind?
Extended solution: Check the process list to see if the old instance is still alive.
Ext. Ext. Problem: What if somebody kills my script?
Ext. Ext. Solution: Trap the abnormal exit and clean up properly.
Ext. Ext. Ext. Problem: What if someone else is invoking a script with exactly the same name as mine?
Ext. Ext. Ext. Solution: You’re screwed. Give your script a really long descriptive name so this won’t happen.

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
#figure out where to put the pid file
myfile=`basename "$0" .sh`
whoiam=`whoami`
pidfile=/tmp/$myfile.pid
[[ "$whoiam" == "root" ]] && pidfile=/var/run/$myfile.pid
 
#remove the pid file cleanly on exit
function cleanup () {
  [[ -f "$pidfile" ]] && rm "$pidfile"
  #add other post processing cleanup here
}
 
# trap all the exit signals for cleanup
trap "cleanup; exit" 0 SIGINT SIGQUIT SIGTERM     # ON OS/X this is 0 2 3 15
 
# Am I already running?
[[ -f "$pidfile" ]] && {
  #pidfile exists, check if previous process exists.
  pid=`head -n 1 $pidfile`
  pidtest="\$1 == $pid { print \$7 }"
  procname=`ps awx | grep $0 | awk "$pidtest"`
  [[ "$procname" == "$0" ]] && {
    echo "Running"
    exit 1
  }
}
 
#put this pid in the file
echo $$ > "$pidfile"

→ No CommentsTags: