Changeset 14480 for trunk/base


Ignore:
Timestamp:
Oct 8, 2005, 6:42:21 PM (19 years ago)
Author:
jberry
Message:

Modify systemstarter support to support the new startupitem keys:

#
# Newly added keys:
#
# startupitem.executable the command to start the executable
# This is exclusive of init, start, stop, restart
# - This may be composed of exec arguments only--not shell code
#
# startupitem.pidfile none
# - There is no pidfile we can track
#
# startupitem.pidfile auto [filename.pid]
# The daemon is responsible for creating/deleting the pidfile
#
# startupitem.pidfile cleanup [filename.pid]
# The daemon creates the pidfile, but we must delete it
#
# startupitem.pidfile manual [filename.pid]
# We create and destroy the pidfile to track the pid we receive from the executable
#
# startupitem.logfile logpath
# Log to the specified file -- if not specified then output to /dev/null
# - for launchd, just set this as the key
# - for systemstarter, redirect to this
#
# startupitem.logevents yes/no
# Log events to the log
# - for launchd, generate log messages inside daemondo
# - for systemstarter, generate log messages in script
#

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/src/port1.0/portstartupitem.tcl

    r14106 r14480  
    22# portstartupitem.tcl
    33#
    4 # $Id: portstartupitem.tcl,v 1.14 2005/09/15 00:44:33 jberry Exp $
     4# $Id: portstartupitem.tcl,v 1.15 2005/10/08 18:42:21 jberry Exp $
    55#
    66# Copyright (c) 2004, 2005 Markus W. Weissman <mww@opendarwin.org>,
     
    3636
    3737#
    38 #       TODO: new keys to add
     38#       Newly added keys:
    3939#
    4040#       startupitem.executable  the command to start the executable
     
    4242#               - This may be composed of exec arguments only--not shell code
    4343#
    44 #       startupitem.pidfile             auto filename.pid
     44#       startupitem.pidfile             none
     45#               - There is no pidfile we can track
     46#
     47#       startupitem.pidfile             auto [filename.pid]
    4548#               The daemon is responsible for creating/deleting the pidfile
    4649#               - We can use this to try to detect if the process is already running
    4750#               - We can use this to try to ensure that the process has stopped
    4851#
    49 #       startupitem.pidfile             cleanup filename.pid
     52#       startupitem.pidfile             cleanup [filename.pid]
    5053#               The daemon creates the pidfile, but we must delete it
    5154#               - We can use this to try to detect if the process is already running
    5255#
    53 #       startupitem.pidfile             manual filename.pid
     56#       startupitem.pidfile             manual [filename.pid]
    5457#               We create and destroy the pidfile to track the pid we receive from the executable
    5558#
     
    121124        global startupitem.start startupitem.stop startupitem.restart
    122125        global startupitem.executable
     126        global startupitem.pidfile startupitem.logfile startupitem.logevents
    123127       
    124128        set scriptdir ${prefix}/etc/startup
    125129       
    126         set itemname                    [string toupper ${startupitem.name}]
    127         set itemdir                             /Library/StartupItems/${startupitem.name}
     130        set itemname                    ${startupitem.name}
     131        set uppername                   [string toupper ${startupitem.name}]
     132        set itemdir                             /Library/StartupItems/${itemname}
    128133        set startupItemDir              ${destroot}${itemdir}
    129         set startupItemScript   ${startupItemDir}/${startupitem.name}
     134        set startupItemScript   ${startupItemDir}/${itemname}
    130135        set startupItemPlist    ${startupItemDir}/StartupParameters.plist
    131136       
    132         file mkdir ${startupItemDir}
    133        
     137        # Interpret the pidfile spec
     138        #
     139        # There are four cases:
     140        #       (1) none (or none specified)
     141        #       (2) auto [pidfilename]
     142        #       (3) cleanup [pidfilename]
     143        #       (4) manual [pidfilename]
     144        #
     145        set createPidFile false
     146        set deletePidFile false
     147        set pidFile ""
     148        set pidfileArgCnt [llength ${startupitem.pidfile}]
     149        if { ${pidfileArgCnt} > 0 } {
     150                if { $pidfileArgCnt == 1 } {
     151                        set pidFile "${prefix}/var/run/${itemname}.pid"
     152                        lappend destroot.keepdirs "${destroot}${prefix}/var/run"
     153                } else {
     154                        set pidFile [lindex ${startupitem.pidfile} 1]
     155                }
     156                if { $pidfileArgCnt > 2 } {
     157                        ui_error "$UI_PREFIX [msgcat::mc "Invalid parameter count to startupitem.pidfile: 2 expected, %d found" ${pidfileArgCnt}]"
     158                }
     159               
     160                set pidStyle [lindex ${startupitem.pidfile} 0]
     161                switch ${pidStyle} {
     162                        none    { set createPidFile false; set deletePidFile false; set pidFile ""      }
     163                        auto    { set createPidFile false; set deletePidFile false      }
     164                        clean   { set createPidFile false; set deletePidFile true       }
     165                        manual  { set createPidFile true;  set deletePidFile true       }
     166                        default {
     167                                ui_error "$UI_PREFIX [msgcat::mc "Unknown pidfile style %s presented to startupitem.pidfile" ${pidStyle}]"
     168                        }
     169                }
     170        }
     171
    134172        if { [llength ${startupitem.executable}] &&
    135173                        ![llength ${startupitem.init}] &&
     
    137175                        ![llength ${startupitem.stop}] &&
    138176                        ![llength ${startupitem.restart}] } {
    139                        
    140177                # An executable is specified, and there is no init, start, stop, or restart
    141                 # code; so we need to gen-up those options
    142                        
    143                 set startupitem.init [list \
    144                         "PIDFILE=${prefix}/var/run/${startupitem.name}.pid-dp" \
    145                         ]
    146 
    147                 set startupitem.start [list \
    148                         "rm -f \$PIDFILE" \
    149                         "${startupitem.executable} &" \
    150                         "echo \$! >\$PIDFILE" \
    151                         ]
    152                        
    153                 set startupitem.stop [list \
    154                         "if test -r \$PIDFILE; then" \
    155                         "\tkill \$(cat \$PIDFILE)" \
    156                         "\trm -f \$PIDFILE" \
    157                         "fi" \
    158                         ]
    159         }
    160        
    161         if { ![llength ${startupitem.start} ] } {
    162                 set startupitem.start [list "sh ${scriptdir}/${portname}.sh start"]
    163         }
    164         if { ![llength ${startupitem.stop} ] } {
    165                 set startupitem.stop [list "sh ${scriptdir}/${portname}.sh stop"]
    166         }
    167         if { ![llength ${startupitem.restart} ] } {
    168                 set startupitem.restart [list StopService StartService]
     178        } else {
     179                if { ![llength ${startupitem.start} ] } {
     180                        set startupitem.start [list "sh ${scriptdir}/${portname}.sh start"]
     181                }
     182                if { ![llength ${startupitem.stop} ] } {
     183                        set startupitem.stop [list "sh ${scriptdir}/${portname}.sh stop"]
     184                }
    169185        }
    170186        if { ![llength ${startupitem.requires} ] } {
    171187                set startupitem.requires [list Disks NFS]
    172188        }
    173 
     189       
     190        ########################
     191        # Create the startup item directory
     192        file mkdir ${startupItemDir}
     193        file attributes ${startupItemDir} -owner root -group wheel
     194       
     195        ########################
    174196        # Generate the startup item script
    175197        set item [open "${startupItemScript}" w 0755]
    176198        file attributes "${startupItemScript}" -owner root -group wheel
    177199       
    178         puts ${item} "#!/bin/sh"
    179         puts ${item} "#"
    180         puts ${item} "# DarwinPorts generated StartupItem"
    181         puts ${item} "#"
     200        # Emit the header
     201        puts ${item} {#!/bin/sh
     202#
     203# DarwinPorts generated StartupItem
     204#
     205
     206# Source the utilities package
     207. /etc/rc.common
     208}
     209
     210        # Emit the Configuration Section
     211        puts ${item} "NAME=${itemname}"
     212        puts ${item} "ENABLE_FLAG=\${${uppername}:=-NO-}"
     213        puts ${item} "PIDFILE=\"${pidFile}\""
     214        puts ${item} "LOGFILE=\"${startupitem.logfile}\""
     215        puts ${item} "EXECUTABLE=\"${startupitem.executable}\""
    182216        puts ${item} ""
    183         puts ${item} ". /etc/rc.common"
     217        puts ${item} "HAVE_STARTCMDS=[expr [llength ${startupitem.start}] ? "true" : "false"]"
     218        puts ${item} "HAVE_STOPCMDS=[expr [llength ${startupitem.stop}] ? "true" : "false"]"
     219        puts ${item} "HAVE_RESTARTCMDS=[expr [llength ${startupitem.restart}] ? "true" : "false"]"
     220        puts ${item} "DELETE_PIDFILE=${createPidFile}"
     221        puts ${item} "CREATE_PIDFILE=${deletePidFile}"
     222        puts ${item} "LOG_EVENTS=[expr [tbool ${startupitem.logevents}] ? "true" : "false"]"
    184223        puts ${item} ""
    185        
     224
     225        # Emit the init lines
    186226        foreach line ${startupitem.init} { puts ${item} ${line} }
    187        
    188         puts ${item} "\nStartService ()\n\{"
    189         puts ${item} "\tif \[ \"\$\{${itemname}:=-NO-\}\" = \"-YES-\" \]; then"
    190         puts ${item} "\t\tConsoleMessage \"Starting ${startupitem.name}\""
    191         foreach line ${startupitem.start} { puts ${item} "\t\t${line}" }
    192         puts ${item} "\tfi\n\}\n"
    193        
    194         puts ${item} "StopService ()\n\{"
    195         puts ${item} "\tConsoleMessage \"Stopping ${startupitem.name}\""
    196         foreach line ${startupitem.stop} { puts ${item} "\t${line}" }
    197         puts ${item} "\}\n"
    198        
    199         puts ${item} "RestartService ()\n\{"
    200         puts ${item} "\tif \[ \"\$\{${itemname}:=-NO-\}\" = \"-YES-\" \]; then"
    201         puts ${item} "\t\tConsoleMessage \"Restarting ${startupitem.name}\""
    202         foreach line ${startupitem.restart} { puts ${item} "\t\t${line}" }
    203         puts ${item} "\tfi\n\}\n"
    204        
    205         puts ${item} "RunService \"\$1\""
     227        puts ${item} ""
     228       
     229        # Emit the _Cmds
     230        foreach kind { start stop restart } {
     231                if {[llength [set "startupitem.$kind"]]} {
     232                        puts ${item} "${kind}Cmds () {"
     233                        foreach line [set "startupitem.$kind"] {
     234                                puts ${item} "\t${line}"
     235                        }
     236                        puts ${item} "}\n"
     237                }
     238        }
     239       
     240        # vvvvv START BOILERPLATE vvvvvv
     241        # Emit the static boilerplate section
     242        puts ${item} {
     243IsEnabled () {
     244        [ "${ENABLE_FLAG}" = "-YES-" ]
     245        return $?
     246}
     247
     248CreatePIDFile () {
     249        echo $1 > "$PIDFILE"
     250}
     251
     252DeletePIDFile () {
     253        rm -f "$PIDFILE"
     254}
     255
     256ReadPID () {
     257        if [ -r "$PIDFILE" ]; then
     258                read pid < "$PIDFILE"
     259        else
     260                pid=0
     261        fi
     262        echo $pid
     263}
     264
     265CheckPID () {
     266        pid=$(ReadPID)
     267        if (($pid)); then
     268                kill -0 $pid >& /dev/null || pid=0
     269        fi
     270        echo $pid
     271}
     272
     273NoteEvent () {
     274        ConsoleMessage "$1"
     275        $LOG_EVENTS && [ -n "$LOGFILE" ] && echo "$(date) $NAME: $1" >> $LOGFILE
     276}
     277
     278StartService () {
     279        if IsEnabled; then
     280                NoteEvent "Starting $NAME"
     281               
     282                if $HAVE_STARTCMDS; then
     283                        startCmds
     284                elif [ -n "$EXECUTABLE" ]; then
     285                        $EXECUTABLE &
     286                        pid=$!
     287                        if $CREATE_PIDFILE; then
     288                                CreatePIDFile $pid
     289                        fi
     290                fi
     291               
     292        fi
     293}
     294
     295StopService () {
     296        NoteEvent "Stopping $NAME"
     297       
     298        gaveup=false
     299        if $HAVE_STOPCMDS; then
     300                # If we have stop cmds, use them
     301                stopCmds
     302        else           
     303                # Otherwise, get the pid and try to stop the program
     304                echo -n "Stopping $NAME..."
     305               
     306                pid=$(CheckPID)
     307                if (($pid)); then
     308                        # Try to kill the process with SIGTERM
     309                        kill $pid
     310                       
     311                        # Wait for it to really stop
     312                        for ((CNT=0; CNT < 15 && $(CheckPID); ++CNT)); do
     313                                echo -n "."
     314                                sleep 1
     315                        done
     316                       
     317                        # Report status
     318                        if (($(CheckPID))); then
     319                                gaveup=true
     320                                echo "giving up."
     321                        else
     322                                echo "stopped."
     323                        fi
     324                else
     325                        echo "it's not running."
     326                fi
     327        fi
     328       
     329        # Cleanup the pidfile if we've been asked to
     330        if ! $gaveup && $DELETE_PIDFILE; then
     331                DeletePIDFile
     332        fi
     333}
     334
     335RestartService () {
     336        if IsEnabled; then
     337                NoteEvent "Restarting $NAME"
     338               
     339                if $HAVE_RESTARTCMDS; then
     340                        # If we have restart cmds, use them
     341                        restartCmds
     342                else
     343                        # Otherwise just stop/start it
     344                        StopService
     345                        StartService
     346                fi
     347               
     348        fi
     349}
     350
     351RunService "$1"
     352}
     353        # ^^^^^^ END BOILERPLATE ^^^^^^
     354       
    206355        close ${item}
    207356       
     357        ########################
    208358        # Generate the plist
    209359        set para [open "${startupItemPlist}" w 0644]
     
    211361       
    212362        puts ${para} "\{"
    213         puts ${para} "\tDescription\t= \"${startupitem.name}\";"
    214         puts ${para} "\tProvides\t= (\"${startupitem.name}\");"
     363        puts ${para} "\tDescription\t= \"${itemname}\";"
     364        puts ${para} "\tProvides\t= (\"${itemname}\");"
    215365        puts -nonewline ${para} "\tRequires\t= ("
    216366        puts -nonewline ${para} [format {"%s"} [join ${startupitem.requires} {", "}]]
     
    234384        set daemondest          LaunchDaemons
    235385        set itemdir                     ${prefix}/etc/${daemondest}/${itemname}
     386        set program                     "${prefix}/bin/daemondo"
    236387        set args                        [list \
    237                                                         "${prefix}/bin/daemondo" \
    238388                                                        "--label=${itemname}" \
    239389                                                        ]
     
    388538        puts ${plist} "<key>Label</key><string>${itemname}</string>"
    389539       
     540        puts ${plist} "<key>Program</key><string>${program}</string>"
    390541        puts ${plist} "<key>ProgramArguments</key>"
    391542        puts ${plist} "<array>"
Note: See TracChangeset for help on using the changeset viewer.