diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | bootrun | 67 | ||||
-rw-r--r-- | timeoutrun | 47 |
3 files changed, 121 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e2130df --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: bootrun timeoutrun + +install: all + install -Dm755 bootrun /etc/rc.d/bootrun + install -Dm755 timeoutrun /usr/lib/bootrun.timeoutrun + +.PHONY: install @@ -0,0 +1,67 @@ +#!/bin/bash + +get_homedirs() { + while read line; do + uname="$(cut -d: -f1 <<< "$line")" + uid="$(cut -d: -f3 <<< "$line")" + udir="$(cut -d: -f6 <<< "$line")" + if [[ "$uid" -ge 1000 ]]; then + echo "$uname:$udir" + fi + done </etc/passwd +} + +start_run() { + rcuser=$2 + rclog="/var/log/bootrun/$rcuser.log" + touch "$rclog" + chmod 600 "$rclog" + chown "$rcuser" "$rclog" + echo "Bootrun on $(date)" >> "$rclog" + su -l "$rcuser" -c "$1" &>> "$rclog" +} + +start() { + touch /var/log/bootrun.log + chmod 640 /var/log/bootrun.log + chown root:log /var/log/bootrun.log + mkdir -p /var/log/bootrun + + for line in $(get_homedirs); do + user="$(cut -d: -f1 <<< "$line")" + file="$(cut -d: -f2 <<< "$line")/.bootrun" + if [ -x "$file" ]; then + start_run "$file" "$user" &>> /var/log/bootrun.log + fi + done +} + +stop_run() { + rcuser=$2 + rclog="/var/log/bootrun/$rcuser.log" + touch "$rclog" + chmod 600 "$rclog" + chown "$rcuser" "$rclog" + echo "Shutdownrun on $(date)" >> "$rclog" + su -l "$rcuser" -c "/usr/lib/bootrun.timoutrun $1" &>> "$rclog" +} + +stop() { + rcpids="" + for line in $(get_homedirs); do + user="$(cut -d: -f1 <<< "$line")" + file="$(cut -d: -f2 <<< "$line")/.shutdownrun" + if [ -x "$file" ]; then + stop_run "$file" "$user" &>> /var/log/bootrun.log & + rcpids="$rcpids $!" + fi + done + + wait $rcpids +} + +case "$1" in + start) start;; + stop) stop;; + *) echo "usage: $0 {start|stop}";; +esac diff --git a/timeoutrun b/timeoutrun new file mode 100644 index 0000000..90f131e --- /dev/null +++ b/timeoutrun @@ -0,0 +1,47 @@ +#!/bin/bash +# +# The Bash shell script executes a command with a time-out. +# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal +# is blocked, then the subsequent SIGKILL (9) terminates it. +# +# Based on the Bash documentation example. + +# Hello Chet, +# please find attached a "little easier" :-) to comprehend +# time-out example. If you find it suitable, feel free to include +# anywhere: the very same logic as in the original examples/scripts, a +# little more transparent implementation to my taste. +# +# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com> + +scriptName="${0##*/}" + +declare -i DEFAULT_TIMEOUT=60 +declare -i DEFAULT_INTERVAL=1 +declare -i DEFAULT_DELAY=2 + +# Timeout. +declare -i timeout=DEFAULT_TIMEOUT +# Interval between checks if the process is still alive. +declare -i interval=DEFAULT_INTERVAL +# Delay between posting the SIGTERM signal and destroying the process by SIGKILL. +declare -i delay=DEFAULT_DELAY + +# kill -0 pid Exit code indicates if a signal may be sent to $pid process. +( + ((t = timeout)) + + while ((t > 0)); do + sleep $interval + kill -0 $$ || exit 0 + ((t -= interval)) + done + + # Be nice, post SIGTERM first. + # The 'exit 0' below will be executed if any preceeding command fails. + kill -s SIGTERM $$ && kill -0 $$ || exit 0 + sleep $delay + kill -s SIGKILL $$ +) 2> /dev/null & + +exec "$@" |