#!/bin/zsh # vim: ft=zsh noet ts=4 sts=4 sw=4 zmodload zsh/stat : ${SVDIR:=/run/service} zparseopts -D \ h=H -help=H \ -all-up=ALL_UP \ -all-down=ALL_DOWN \ -new-down=NEW_DOWN \ -lock+:=LOCK \ f+:=F -filter+:=F if [[ -n $H ]]; then cat < 1 )); then printf '%s\n' "Only one of following options is allowed:" \ " --all-up --all-down --new-down" exit 2 fi if [[ -n $1 ]]; then exec >>$1 2>&1 shift zmodload zsh/datetime zsh/system print -r - "$(strftime '%Y-%m-%d %H:%M:%S' $EPOCHSECONDS) started: ${(qqq)0}" "${(qqq)@} (pid: $$)" PS4='+%B${SECONDS} ${sysparams[pid]} %N:%i>%b ' set -x fi service_patterns=() for pat in $F; do case $pat in (-f);; (--filter);; (*) service_patterns+=( $pat );; esac done typeset -A remove autoload -Uz zsv_config zsv_config zsv_parse if (($#LOCK)); then LOCK_TIMEOUT=$LOCK[-1] if ! [[ $LOCK_TIMEOUT =~ '^[0-9]+$' ]]; then printf 'Incorrect lock timeout: "%s"\n' $LOCK_TIMEOUT exit 2 fi exec 3> ${ZSVDIR}.lock if ! flock -w $LOCK_TIMEOUT 3; then exit 3 fi fi for d in $ZSVDIR/*(N/); do [[ $d == $ZSVDIR/_* ]] && continue if (($#service_patterns)); then for pat in $service_patterns; do if [[ $d:t == $~pat ]]; then remove[$d:t]=$d break fi done else remove[$d:t]=$d fi done sv_mkdir=${SVDIR%%/} typeset -gA svdir_stat zstat -L -H svdir_stat $sv_mkdir && \ while (( $svdir_stat[mode] >> 12 == 10 )); do # symlink sv_mkdir=$svdir_stat[link] zstat -L -H svdir_stat $sv_mkdir || break done mkdir -p $sv_mkdir || exit $? for name in $svtab; do unset "remove[$name]" if (($#service_patterns)); then pat_matches=0 for pat in $service_patterns; do if [[ $name == $~pat ]]; then pat_matches=1 break fi done (($pat_matches)) || continue unset pat pat_matches fi zsv_eval $ZSVDIR/$name zsv_dir=$zsv_svdir/$name if (($#NEW_DOWN)); then if ! [[ -d $ZSVDIR/_ovr/$name ]]; then mkdir -p $zsv_dir $ZSVDIR/_ovr/$name touch $ZSVDIR/_ovr/$name/down fi else mkdir -p $zsv_dir $ZSVDIR/_ovr/$name if (($#ALL_UP)); then [[ -e $ZSVDIR/_ovr/$name/down ]] && rm $ZSVDIR/_ovr/$name/down elif (($#ALL_DOWN)); then touch $ZSVDIR/_ovr/$name/down fi fi # flags if (( ${flags[M]} )); then # Manual touch $zsv_dir/down else # check if the service should be up if [[ ! -e $ZSVDIR/_ovr/$name/down ]] && \ $handler[cond] && ! [[ -f ${SVDIR}/down ]] ; then rm -f $zsv_dir/down sv up $zsv_dir else touch $zsv_dir/down sv down $zsv_dir fi fi # run for f in run check finish control/{u,d,o,p,c,h,a,i,q,1,2,t,k,x}; do if zsv_has_handler $f:t; then [[ -L $zsv_dir/$f ]] && rm $zsv_dir/$f mkdir -p $zsv_dir/$f:h ln -s ${commands[zsv.exec]} $zsv_dir/$f else rm -f $zsv_dir/$f fi done # log if [[ $handler[log] != '-' ]]; then mkdir -p $zsv_dir/log [[ -L $zsv_dir/log/run ]] && rm $zsv_dir/log/run ln -s ${commands[zsv.exec]} $zsv_dir/log/run elif [[ -e $zsv_dir/log ]]; then rm -rf $zsv_dir/log fi # make symlink [[ -L ${SVDIR}/$name ]] && rm ${SVDIR}/$name ln -s ../zsv/$name ${SVDIR} done # for name in $svtab; do # [[ -L ${SVDIR}/$name ]] && rm ${SVDIR}/$name # ln -s ../zsv/$name ${SVDIR} # done if (($#remove)); then rm -f ${SVDIR}/${^remove:t} sv_exit=( $^remove/supervise/control(N) ) (($#sv_exit)) && sv exit $sv_exit:h:h rm -rf $remove fi broken=( ${SVDIR}/*(-@N) ) (($#broken)) && rm -f $broken # make runsvdir re-read the directories killall --signal CONT --user ${USER:-root} runsvdir &>/dev/null touch ${SVDIR}/.zsv