@@ -1135,8 +1135,8 @@ function zypper_install {
11351135# fork. It includes the dirty work of closing extra filehandles and preparing log
11361136# files to produce the same logs as screen_it(). The log filename is derived
11371137# from the service name and global-and-now-misnamed ``SCREEN_LOGDIR``
1138- # Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_LOGDIR``
1139- # _run_process service "command-line"
1138+ # Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_LOGDIR``, ``SCREEN_NAME``, ``SERVICE_DIR``
1139+ # _old_run_process service "command-line"
11401140function _run_process {
11411141 local service=$1
11421142 local command="$2"
@@ -1155,8 +1155,12 @@ function _run_process {
11551155 export PYTHONUNBUFFERED=1
11561156 fi
11571157
1158- exec /bin/bash -c "$command"
1159- die "$service exec failure: $command"
1158+ # Run under ``setsid`` to force the process to become a session and group leader.
1159+ # The pid saved can be used with pkill -g to get the entire process group.
1160+ setsid $command & echo $! >$SERVICE_DIR/$SCREEN_NAME/$1.pid
1161+
1162+ # Just silently exit this process
1163+ exit 0
11601164}
11611165
11621166# Helper to remove the ``*.failure`` files under ``$SERVICE_DIR/$SCREEN_NAME``.
@@ -1184,61 +1188,63 @@ function is_running {
11841188 return $exitcode
11851189}
11861190
1187- # run_process() launches a child process that closes all file descriptors and
1188- # then exec's the passed in command. This is meant to duplicate the semantics
1189- # of screen_it() without screen. PIDs are written to
1190- # ``$SERVICE_DIR/$SCREEN_NAME/$service.pid``
1191+ # Run a single service under screen or directly
1192+ # If the command includes shell metachatacters (;<>*) it must be run using a shell
11911193# run_process service "command-line"
11921194function run_process {
11931195 local service=$1
11941196 local command="$2"
11951197
1196- # Spawn the child process
1197- _run_process "$service" "$command" &
1198- echo $!
1198+ if is_service_enabled $service; then
1199+ if [[ "$USE_SCREEN" = "True" ]]; then
1200+ screen_service "$service" "$command"
1201+ else
1202+ # Spawn directly without screen
1203+ _run_process "$service" "$command" &
1204+ fi
1205+ fi
11991206}
12001207
12011208# Helper to launch a service in a named screen
12021209# Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_NAME``, ``SCREEN_LOGDIR``,
12031210# ``SERVICE_DIR``, ``USE_SCREEN``
1204- # screen_it service "command-line"
1205- function screen_it {
1211+ # screen_service service "command-line"
1212+ # Run a command in a shell in a screen window
1213+ function screen_service {
1214+ local service=$1
1215+ local command="$2"
1216+
12061217 SCREEN_NAME=${SCREEN_NAME:-stack}
12071218 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
12081219 USE_SCREEN=$(trueorfalse True $USE_SCREEN)
12091220
1210- if is_service_enabled $1 ; then
1221+ if is_service_enabled $service ; then
12111222 # Append the service to the screen rc file
1212- screen_rc "$1 " "$2 "
1223+ screen_rc "$service " "$command "
12131224
1214- if [[ "$USE_SCREEN" = "True" ]]; then
1215- screen -S $SCREEN_NAME -X screen -t $1
1216-
1217- if [[ -n ${SCREEN_LOGDIR} ]]; then
1218- screen -S $SCREEN_NAME -p $1 -X logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log
1219- screen -S $SCREEN_NAME -p $1 -X log on
1220- ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
1221- fi
1225+ screen -S $SCREEN_NAME -X screen -t $service
12221226
1223- # sleep to allow bash to be ready to be send the command - we are
1224- # creating a new window in screen and then sends characters, so if
1225- # bash isn't running by the time we send the command, nothing happens
1226- sleep 3
1227-
1228- NL=`echo -ne '\015'`
1229- # This fun command does the following:
1230- # - the passed server command is backgrounded
1231- # - the pid of the background process is saved in the usual place
1232- # - the server process is brought back to the foreground
1233- # - if the server process exits prematurely the fg command errors
1234- # and a message is written to stdout and the service failure file
1235- # The pid saved can be used in screen_stop() as a process group
1236- # id to kill off all child processes
1237- screen -S $SCREEN_NAME -p $1 -X stuff "$2 & echo \$! >$SERVICE_DIR/$SCREEN_NAME/$1.pid; fg || echo \"$1 failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL"
1238- else
1239- # Spawn directly without screen
1240- run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$1.pid
1227+ if [[ -n ${SCREEN_LOGDIR} ]]; then
1228+ screen -S $SCREEN_NAME -p $service -X logfile ${SCREEN_LOGDIR}/screen-${service}.${CURRENT_LOG_TIME}.log
1229+ screen -S $SCREEN_NAME -p $service -X log on
1230+ ln -sf ${SCREEN_LOGDIR}/screen-${service}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${service}.log
12411231 fi
1232+
1233+ # sleep to allow bash to be ready to be send the command - we are
1234+ # creating a new window in screen and then sends characters, so if
1235+ # bash isn't running by the time we send the command, nothing happens
1236+ sleep 3
1237+
1238+ NL=`echo -ne '\015'`
1239+ # This fun command does the following:
1240+ # - the passed server command is backgrounded
1241+ # - the pid of the background process is saved in the usual place
1242+ # - the server process is brought back to the foreground
1243+ # - if the server process exits prematurely the fg command errors
1244+ # and a message is written to stdout and the service failure file
1245+ # The pid saved can be used in screen_stop() as a process group
1246+ # id to kill off all child processes
1247+ screen -S $SCREEN_NAME -p $service -X stuff "$command & echo \$! >$SERVICE_DIR/$SCREEN_NAME/${service}.pid; fg || echo \"$service failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/${service}.failure\"$NL"
12421248 fi
12431249}
12441250
@@ -1276,20 +1282,40 @@ function screen_rc {
12761282# that did not leave a PID behind
12771283# Uses globals ``SCREEN_NAME``, ``SERVICE_DIR``, ``USE_SCREEN``
12781284# screen_stop service
1279- function screen_stop {
1285+ function screen_stop_service {
1286+ local service=$1
1287+
12801288 SCREEN_NAME=${SCREEN_NAME:-stack}
12811289 SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
12821290 USE_SCREEN=$(trueorfalse True $USE_SCREEN)
12831291
1284- if is_service_enabled $1; then
1292+ if is_service_enabled $service; then
1293+ # Clean up the screen window
1294+ screen -S $SCREEN_NAME -p $service -X kill
1295+ fi
1296+ }
1297+
1298+ # Stop a service process
1299+ # If a PID is available use it, kill the whole process group via TERM
1300+ # If screen is being used kill the screen window; this will catch processes
1301+ # that did not leave a PID behind
1302+ # Uses globals ``SERVICE_DIR``, ``USE_SCREEN``
1303+ # stop_process service
1304+ function stop_process {
1305+ local service=$1
1306+
1307+ SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
1308+ USE_SCREEN=$(trueorfalse True $USE_SCREEN)
1309+
1310+ if is_service_enabled $service; then
12851311 # Kill via pid if we have one available
1286- if [[ -r $SERVICE_DIR/$SCREEN_NAME/$1 .pid ]]; then
1287- pkill -TERM -P - $(cat $SERVICE_DIR/$SCREEN_NAME/$1 .pid)
1288- rm $SERVICE_DIR/$SCREEN_NAME/$1 .pid
1312+ if [[ -r $SERVICE_DIR/$SCREEN_NAME/$service .pid ]]; then
1313+ pkill -g $(cat $SERVICE_DIR/$SCREEN_NAME/$service .pid)
1314+ rm $SERVICE_DIR/$SCREEN_NAME/$service .pid
12891315 fi
12901316 if [[ "$USE_SCREEN" = "True" ]]; then
12911317 # Clean up the screen window
1292- screen -S $SCREEN_NAME -p $1 -X kill
1318+ screen_stop_service $service
12931319 fi
12941320 fi
12951321}
@@ -1325,6 +1351,80 @@ function service_check {
13251351}
13261352
13271353
1354+ # Deprecated Functions
1355+ # --------------------
1356+
1357+ # _old_run_process() is designed to be backgrounded by old_run_process() to simulate a
1358+ # fork. It includes the dirty work of closing extra filehandles and preparing log
1359+ # files to produce the same logs as screen_it(). The log filename is derived
1360+ # from the service name and global-and-now-misnamed ``SCREEN_LOGDIR``
1361+ # Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_LOGDIR``, ``SCREEN_NAME``, ``SERVICE_DIR``
1362+ # _old_run_process service "command-line"
1363+ function _old_run_process {
1364+ local service=$1
1365+ local command="$2"
1366+
1367+ # Undo logging redirections and close the extra descriptors
1368+ exec 1>&3
1369+ exec 2>&3
1370+ exec 3>&-
1371+ exec 6>&-
1372+
1373+ if [[ -n ${SCREEN_LOGDIR} ]]; then
1374+ exec 1>&${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log 2>&1
1375+ ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
1376+
1377+ # TODO(dtroyer): Hack to get stdout from the Python interpreter for the logs.
1378+ export PYTHONUNBUFFERED=1
1379+ fi
1380+
1381+ exec /bin/bash -c "$command"
1382+ die "$service exec failure: $command"
1383+ }
1384+
1385+ # old_run_process() launches a child process that closes all file descriptors and
1386+ # then exec's the passed in command. This is meant to duplicate the semantics
1387+ # of screen_it() without screen. PIDs are written to
1388+ # ``$SERVICE_DIR/$SCREEN_NAME/$service.pid`` by the spawned child process.
1389+ # old_run_process service "command-line"
1390+ function old_run_process {
1391+ local service=$1
1392+ local command="$2"
1393+
1394+ # Spawn the child process
1395+ _old_run_process "$service" "$command" &
1396+ echo $!
1397+ }
1398+
1399+ # Compatibility for existing start_XXXX() functions
1400+ # Uses global ``USE_SCREEN``
1401+ # screen_it service "command-line"
1402+ function screen_it {
1403+ if is_service_enabled $1; then
1404+ # Append the service to the screen rc file
1405+ screen_rc "$1" "$2"
1406+
1407+ if [[ "$USE_SCREEN" = "True" ]]; then
1408+ screen_service "$1" "$2"
1409+ else
1410+ # Spawn directly without screen
1411+ old_run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$1.pid
1412+ fi
1413+ fi
1414+ }
1415+
1416+ # Compatibility for existing stop_XXXX() functions
1417+ # Stop a service in screen
1418+ # If a PID is available use it, kill the whole process group via TERM
1419+ # If screen is being used kill the screen window; this will catch processes
1420+ # that did not leave a PID behind
1421+ # screen_stop service
1422+ function screen_stop {
1423+ # Clean up the screen window
1424+ stop_process $1
1425+ }
1426+
1427+
13281428# Python Functions
13291429# ================
13301430
0 commit comments