fix that modified shells were not properly handled. Add status, color, and json5 output
This commit is contained in:
354
shellbox
354
shellbox
@@ -5,26 +5,21 @@
|
||||
|
||||
HOME=/root
|
||||
. /etc/profile
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
|
||||
|
||||
export PATH=$PATH:/usr/local/bin
|
||||
|
||||
# AD84: export HOSTNAME=$(hostname -s)
|
||||
|
||||
|
||||
# AD84: added
|
||||
if [ -f /usr/local/bin/getIocBootEnv ]
|
||||
then
|
||||
. /usr/local/bin/getIocBootEnv
|
||||
#echo ""
|
||||
#echo "shellbox: IOC=$IOC"
|
||||
#echo "shellbox: FACILITY=$FACILITY"
|
||||
#echo "shellbox: ROOTFSSERVERIP=$ROOTFSSERVERIP"
|
||||
#echo "shellbox: BOOTPC=$BOOTPC"
|
||||
#echo "shellbox: CMDLINE_HOST=$CMDLINE_HOST"
|
||||
#echo "shellbox: CMDLINE_ETH=$CMDLINE_ETH"
|
||||
#echo "shellbox: BOOTIF_BCAST=$BOOTIF_BCAST"
|
||||
#echo "shellbox: BOOTIF_IP=$BOOTIF_IP"
|
||||
#echo ""
|
||||
#echo ""
|
||||
#echo "shellbox: IOC=$IOC"
|
||||
#echo "shellbox: FACILITY=$FACILITY"
|
||||
#echo "shellbox: ROOTFSSERVERIP=$ROOTFSSERVERIP"
|
||||
#echo "shellbox: BOOTPC=$BOOTPC"
|
||||
#echo "shellbox: CMDLINE_HOST=$CMDLINE_HOST"
|
||||
#echo "shellbox: CMDLINE_ETH=$CMDLINE_ETH"
|
||||
#echo "shellbox: BOOTIF_BCAST=$BOOTIF_BCAST"
|
||||
#echo "shellbox: BOOTIF_IP=$BOOTIF_IP"
|
||||
#echo ""
|
||||
fi
|
||||
if [ "$IOC" == "" ]
|
||||
then
|
||||
@@ -33,28 +28,39 @@ else
|
||||
HOSTNAME=$IOC
|
||||
fi
|
||||
export HOSTNAME
|
||||
# AD84: end added
|
||||
|
||||
fail () {
|
||||
echo $@ >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
exe=/usr/local/bin/procServ
|
||||
options="-k ^X --killsig 15 -x ^D -i ^C --allow -c"
|
||||
prog=shellbox
|
||||
params=
|
||||
conf=/etc/shellbox.conf
|
||||
logdir=/var/log/$prog
|
||||
shells=/var/run/$prog
|
||||
|
||||
fail () {
|
||||
echo $@
|
||||
exit 1
|
||||
}
|
||||
# color only if printing to terminal
|
||||
declare -A COLOR
|
||||
if [ -t 1 ]
|
||||
then
|
||||
COLOR[RUNNING]=
|
||||
COLOR[STOPPED]=$'\033[46;30m'
|
||||
COLOR[DISABLED]=$'\033[47;38;5;8m'
|
||||
COLOR[OBSOLETE]=$'\033[48;5;8;37m'
|
||||
COLOR[MODIFIED]=$'\033[43;30m'
|
||||
COLOR[DEAD]=$'\033[41;37m'
|
||||
COLOR[NORMAL]=$'\033[0;39m'
|
||||
COLOR[HEADER]=$'\033[0;1;4m'
|
||||
fi
|
||||
|
||||
|
||||
echo_failure () {
|
||||
echo " [failed]"
|
||||
}
|
||||
|
||||
checkpid () {
|
||||
[ -d /proc/$PID ]
|
||||
[ -d /proc/$* ]
|
||||
}
|
||||
|
||||
launch () {
|
||||
@@ -64,87 +70,129 @@ launch () {
|
||||
reload=YES
|
||||
shift
|
||||
fi
|
||||
|
||||
[ -d /var/run/procServ ] || mkdir -pm 755 /var/run/procServ
|
||||
[ -z "$logdir" -o -d "$logdir" ] || mkdir -pm 755 "$logdir"
|
||||
|
||||
temp=$(mktemp -p $(dirname $shells)) || fail "can't create temporary file"
|
||||
while read PORT USER DIR COMMAND ARGS
|
||||
do
|
||||
# check for empty lines and comments
|
||||
[[ $PORT == "" || $PORT == \#* ]] && continue
|
||||
|
||||
# AD84: added
|
||||
DIR=${DIR//_IOCNAME_/$HOSTNAME}
|
||||
ARGS=${ARGS//_IOCNAME_/$HOSTNAME}
|
||||
# AD84: end added
|
||||
|
||||
# check if already started shell is still alive
|
||||
if LINE=$(grep "$PORT $USER $DIR $COMMAND $ARGS" $shells 2> /dev/null)
|
||||
then
|
||||
PID=${LINE%% *}
|
||||
if checkpid $PID
|
||||
# delete entries for dead shell that we are going to restart
|
||||
if [ -f $shells ]
|
||||
then
|
||||
while read -r PID PORT LINE
|
||||
do
|
||||
if ! checkpid $PID
|
||||
then
|
||||
if [ -z "$reload" ] && [ -z "$*" ] || echo "$*" | grep -qE "(^|[[:space:]])$PORT([[:space:]]|$)"
|
||||
then
|
||||
echo "Already running: $PORT $USER $DIR $COMMAND $ARGS"
|
||||
fi
|
||||
echo "$LINE" >> $temp
|
||||
continue
|
||||
[ -z "$*" ] && continue
|
||||
for p in "$@"; do [ "$p" = "$PORT" ] && continue 2; done
|
||||
fi
|
||||
# keep all other shell entries (dead or running)
|
||||
echo "$PID $PORT $LINE" >> $temp
|
||||
_PID[$PORT]=$PID
|
||||
_LINE[$PORT]="$LINE"
|
||||
done < $shells
|
||||
fi
|
||||
|
||||
# add entries for shells we start
|
||||
while read -r PORT USER DIR COMMAND
|
||||
do
|
||||
# ignore empty lines and comments
|
||||
[ "${PORT%#*}" ] && STATUS=STOPPED || STATUS=DISABLED
|
||||
PORT="${PORT#\#}"
|
||||
test "$PORT" -ge 0 2>/dev/null || continue
|
||||
|
||||
# skip if line does not match given port number
|
||||
if [ "$*" ]
|
||||
then
|
||||
for p in "$@" end; do [ "$p" = "$PORT" ] && break; done
|
||||
[ $p = end ] && continue
|
||||
fi
|
||||
|
||||
# check if we have to start all shells or only this PORT
|
||||
[ "$*" ] && echo "$*" | grep -qvE "(^|[[:space:]])$PORT([[:space:]]|$)" && continue
|
||||
if [ $STATUS = DISABLED ]
|
||||
then
|
||||
echo "Shell $PORT has been disabled in the configuration" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
DIR=${DIR//_IOCNAME_/$HOSTNAME}
|
||||
ARGS=${ARGS//_IOCNAME_/$HOSTNAME}
|
||||
|
||||
# check if this shell had already been started
|
||||
if [ "${_PID[$PORT]}" ]
|
||||
then
|
||||
# warn if trying to start already running shell
|
||||
if [ -z "$reload" ]
|
||||
then
|
||||
if [ "$USER $DIR $COMMAND" != "${_LINE[$PORT]}" ]
|
||||
then
|
||||
echo "Running but modified: ${_LINE[$PORT]}" >&2
|
||||
echo "New configuration : $USER $DIR $COMMAND" >&2
|
||||
echo "You may want to restart $PORT" >&2
|
||||
mod=1
|
||||
else
|
||||
echo "Already running: $PORT ${_LINE[$PORT]}" >&2
|
||||
fi
|
||||
fi
|
||||
# skip already running shells
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -n "$logdir" ]
|
||||
then
|
||||
[ -d $logdir ] || mkdir -m 777 $logdir
|
||||
LOG=$logdir/$PORT
|
||||
rm -f $LOG
|
||||
else
|
||||
LOG=/dev/null
|
||||
fi
|
||||
|
||||
# start shellbox as other user
|
||||
echo -n Starting: $PORT $USER $DIR $COMMAND $ARGS
|
||||
|
||||
if /usr/bin/sudo -E true 2> /dev/null
|
||||
# start shell
|
||||
echo Starting: $PORT $USER $DIR $COMMAND
|
||||
if [ "$UID" -eq 0 ]
|
||||
then
|
||||
SUDO="/usr/bin/sudo -H -u $USER SHELLBOX=$HOSTNAME:$PORT EPICS_HOST_ARCH=$EPICS_HOST_ARCH PATH=$PATH"
|
||||
elif /usr/bin/sudo true 2> /dev/null
|
||||
then
|
||||
SUDO="/usr/bin/sudo -H -u $USER"
|
||||
# sudo may be installed in different locations
|
||||
# and may delete important environment variables
|
||||
SUDO=$(which sudo) && SUDO+=" -H -u $USER SHELLBOX=$HOSTNAME:$PORT EPICS_HOST_ARCH=$EPICS_HOST_ARCH PATH=$PATH"
|
||||
fi
|
||||
|
||||
SUDO="/usr/bin/sudo -H -u $USER SHELLBOX=$HOSTNAME:$PORT EPICS_HOST_ARCH=$EPICS_HOST_ARCH PATH=$PATH"
|
||||
|
||||
#export SHELLBOX=$HOSTNAME:$PORT
|
||||
|
||||
pidfile=/var/run/procServ-$PORT.pid
|
||||
pidfile=/var/run/procServ/$PORT.pid
|
||||
rm -f $pidfile
|
||||
L=/tmp/$SHELLBOX.log
|
||||
mknod -m 666 $L p 2>/dev/null
|
||||
logger -p local0.info -t shellbox["$PORT"] -f $L &
|
||||
$exe -p $pidfile $options $DIR $params -L $L $PORT $SUDO $(which $COMMAND) $ARGS >> $LOG 2>&1 < /dev/null
|
||||
logpipe=/tmp/procServ-$PORT.log
|
||||
mknod -m 666 $logpipe p 2>/dev/null
|
||||
cat $logpipe | logger -p local0.info -t shellbox[$PORT] 2>/dev/null &
|
||||
$exe -p $pidfile $options $DIR -L $logpipe $PORT $SUDO $COMMAND >> $LOG 2>&1 < /dev/null
|
||||
# check if starting worked or failed
|
||||
usleep 100000
|
||||
if [ -e $pidfile ]
|
||||
then
|
||||
PID=$(<$pidfile)
|
||||
echo "$PID $PORT $USER $DIR $COMMAND $ARGS" >> $temp
|
||||
echo
|
||||
_PID[$PORT]=$PID
|
||||
echo "$PID $PORT $USER $DIR $COMMAND" >> $temp
|
||||
else
|
||||
_PID[$PORT]=fail
|
||||
echo_failure
|
||||
echo
|
||||
cat $LOG
|
||||
fi
|
||||
done < $conf
|
||||
mv $temp $shells
|
||||
chmod 0644 $shells
|
||||
chmod 0444 $shells
|
||||
for p in "$@"
|
||||
do
|
||||
if [ -z ${_PID[$p]]} ]
|
||||
then
|
||||
echo "No configuration for $p found" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
[ "$mod" ] && fail "To apply all modifcations use reload"
|
||||
}
|
||||
|
||||
start () {
|
||||
[ -r $conf ] || fail "$conf not readable"
|
||||
exe=$(which procServ) || fail "procServ not found"
|
||||
[ -x $exe ] || fail "$exe is not executable"
|
||||
launch $*
|
||||
mkdir -pm 755 /var/lock/subsys
|
||||
touch /var/lock/subsys/$prog
|
||||
launch $*
|
||||
}
|
||||
|
||||
stopshell() {
|
||||
@@ -162,7 +210,7 @@ stopshell() {
|
||||
|
||||
stop () {
|
||||
# anything to stop?
|
||||
if [ ! -r $shells ]
|
||||
if [ ! -f $shells ]
|
||||
then
|
||||
echo "$prog: No shells started."
|
||||
exit 0
|
||||
@@ -170,7 +218,7 @@ stop () {
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
# kill all shellboxes
|
||||
while read PID PORT ARGS
|
||||
while read -r PID PORT ARGS
|
||||
do
|
||||
stopshell $PID $PORT $ARGS
|
||||
done < $shells
|
||||
@@ -179,31 +227,32 @@ stop () {
|
||||
else
|
||||
# kill only selected shellboxes
|
||||
temp=$(mktemp -p $(dirname $shells)) || fail "can't create temporary file"
|
||||
while read PID PORT ARGS
|
||||
while read -r PID PORT ARGS
|
||||
do
|
||||
echo "$*" | grep -qE "(^|[[:space:]])$PORT([[:space:]]|$)" && stopshell $PID $PORT $ARGS || echo "$PID $PORT $ARGS" >> $temp
|
||||
echo "$*" | grep -qE "(^|[[:space:]])$PORT([[:space:]]|$)" && \
|
||||
stopshell $PID $PORT $ARGS || \
|
||||
echo "$PID $PORT $ARGS" >> $temp
|
||||
done < $shells
|
||||
mv $temp $shells
|
||||
chmod 0644 $shells
|
||||
chmod 0444 $shells
|
||||
fi
|
||||
}
|
||||
|
||||
reload () {
|
||||
echo "Reloading $conf: "
|
||||
[ -r $conf ] || fail "not readable"
|
||||
echo "Reloading $conf... "
|
||||
[ -f $conf ] || fail "not readable"
|
||||
# anything to stop?
|
||||
if [ -r $shells ]
|
||||
if [ -f $shells ]
|
||||
then
|
||||
#first kill all shells that are not configured any more
|
||||
# first kill all shells that are modified or not configured any more
|
||||
temp=$(mktemp -p $(dirname $shells)) || fail "can't create temporary file"
|
||||
while read PID LINE
|
||||
while read -r PID LINE
|
||||
do
|
||||
while read PORT USER DIR COMMAND ARGS
|
||||
while read -r PORT USER DIR COMMAND ARGS
|
||||
do
|
||||
# AD84: added
|
||||
DIR=${DIR//_IOCNAME_/$HOSTNAME}
|
||||
ARGS=${ARGS//_IOCNAME_/$HOSTNAME}
|
||||
# AD84: end added
|
||||
|
||||
if [ "$PORT $USER $DIR $COMMAND $ARGS" = "$LINE" ]
|
||||
then
|
||||
echo "Keeping: $LINE"
|
||||
@@ -214,62 +263,123 @@ reload () {
|
||||
stopshell $PID $PORT $LINE
|
||||
done < $shells
|
||||
mv $temp $shells
|
||||
chmod 0644 $shells
|
||||
chmod 0444 $shells
|
||||
fi
|
||||
#now start all new shells
|
||||
# now start all new or modified shells
|
||||
sleep 2
|
||||
launch -reload
|
||||
}
|
||||
|
||||
status () {
|
||||
[ -r $conf ] || fail "$conf not readable"
|
||||
if [ "$1" = "-log" ]
|
||||
then
|
||||
log=YES
|
||||
shift
|
||||
fi
|
||||
echo -e "pid\tport\tuser\tdir\t\t\tcommand"
|
||||
while read PORT USER DIR COMMAND ARGS
|
||||
while [ "$1" ]
|
||||
do
|
||||
# check for empty lines and comments
|
||||
[[ $PORT == "" || $PORT == \#* ]] && continue
|
||||
case "$1" in
|
||||
-log | --log) log=1; shift ;;
|
||||
--json5) json5=1; shift ;;
|
||||
--) shift; break;;
|
||||
-* ) echo "unknown option $1 ignored" >&2; shift ;;
|
||||
*) break
|
||||
esac
|
||||
done
|
||||
|
||||
# AD84: added
|
||||
DIR=${DIR//_IOCNAME_/$HOSTNAME}
|
||||
ARGS=${ARGS//_IOCNAME_/$HOSTNAME}
|
||||
# AD84: end added
|
||||
# First read all configured shells
|
||||
if [ -f $conf ]
|
||||
then
|
||||
while read -r PORT USER DIR CMD
|
||||
do
|
||||
# Assume stopped until proven otherwise
|
||||
[ "${PORT%#*}" ] && STATUS=STOPPED || STATUS=DISABLED
|
||||
# check for empty lines, comments, rubbish
|
||||
PORT="${PORT#\#}"
|
||||
test "$PORT" -ge 0 2>/dev/null || continue
|
||||
_STATUS[$PORT]=$STATUS
|
||||
_USER[$PORT]=$USER
|
||||
_DIR[$PORT]=${DIR//_IOCNAME_/$HOSTNAME}
|
||||
_CMD[$PORT]=${CMD//_IOCNAME_/$HOSTNAME}
|
||||
_CFG[$PORT]="${_USER[$PORT]} ${_DIR[$PORT]} ${_CMD[$PORT]}"
|
||||
done < $conf
|
||||
fi
|
||||
|
||||
# check if we have to report all shells
|
||||
[ "$*" ] && echo "$*" | grep -qvE "(^|[[:space:]])$PORT([[:space:]]|$)" && continue
|
||||
|
||||
if [ "$logdir" -a "$log" ]
|
||||
then
|
||||
echo "-------------------------------------------------------------------"
|
||||
fi
|
||||
|
||||
if LINE=$(grep "$PORT $USER $DIR $COMMAND $ARGS" $shells 2> /dev/null)
|
||||
then
|
||||
PID=${LINE%% *}
|
||||
# Now check all started shells
|
||||
if [ -f $shells ]
|
||||
then
|
||||
while read -r PID PORT USER DIR CMD
|
||||
do
|
||||
CFG="$USER $DIR $CMD"
|
||||
_PID[$PORT]=$PID
|
||||
_USER[$PORT]=$USER
|
||||
_DIR[$PORT]=$DIR
|
||||
_CMD[$PORT]=$CMD
|
||||
if checkpid $PID
|
||||
then
|
||||
echo -n $PID
|
||||
if [ "${_STATUS[$PORT]}" = DISABLED ]
|
||||
then
|
||||
_STATUS[$PORT]=OBSOLETE
|
||||
elif [ -z "${_CFG[$PORT]}" ]
|
||||
then
|
||||
_STATUS[$PORT]=OBSOLETE
|
||||
elif [ "${_CFG[$PORT]}" != "$CFG" ]
|
||||
then
|
||||
_STATUS[$PORT]=MODIFIED
|
||||
else
|
||||
_STATUS[$PORT]=RUNNING
|
||||
fi
|
||||
else
|
||||
$SETCOLOR_FAILURE
|
||||
echo -n DEAD
|
||||
$SETCOLOR_NORMAL
|
||||
_STATUS[$PORT]=DEAD
|
||||
_PID[$PORT]=
|
||||
fi
|
||||
else
|
||||
$SETCOLOR_FAILURE
|
||||
echo -n STOPPED
|
||||
$SETCOLOR_NORMAL
|
||||
fi
|
||||
echo -e "\t$PORT\t$USER\t$DIR\t$COMMAND $ARGS"
|
||||
|
||||
done < $shells
|
||||
fi
|
||||
|
||||
|
||||
if [ "$json5" ]
|
||||
then
|
||||
echo '{ shells: ['
|
||||
for PORT in ${!_STATUS[*]}
|
||||
do
|
||||
echo ' {'
|
||||
echo ' port: '$PORT','
|
||||
[ "${_PID[$PORT]}" ] && echo ' pid: '${_PID[$PORT]}','
|
||||
echo ' status: "'${_STATUS[$PORT]}'",'
|
||||
echo ' user: "'${_USER[$PORT]}'",'
|
||||
dir=${_DIR[$PORT]//\\/\\\\}
|
||||
echo ' dir: "'${dir//\"/\\\"}'",'
|
||||
cmd=${_CMD[$PORT]//\\/\\\\}
|
||||
echo ' cmd: "'${cmd//\"/\\\"}'"'
|
||||
echo ' },'
|
||||
done
|
||||
echo ']}'
|
||||
exit
|
||||
fi
|
||||
|
||||
USERLEN=0
|
||||
for v in "${_USER[@]}"
|
||||
do
|
||||
[ ${#v} -gt $USERLEN ] && USERLEN=${#v}
|
||||
done
|
||||
DIRLEN=0
|
||||
for v in "${_DIR[@]}"
|
||||
do
|
||||
[ ${#v} -gt $DIRLEN ] && DIRLEN=${#v}
|
||||
done
|
||||
CMDLEN=0
|
||||
for v in "${_CMD[@]}"
|
||||
do
|
||||
[ ${#v} -gt $CMDLEN ] && CMDLEN=${#v}
|
||||
done
|
||||
|
||||
printf "${COLOR[HEADER]}#%-5s %-8s %-5s %-*s %-*s %-*s ${COLOR[NORMAL]}\n" pid status port $USERLEN user $DIRLEN dir $CMDLEN command
|
||||
|
||||
for PORT in ${!_STATUS[*]}
|
||||
do
|
||||
# check if we have to report all shells
|
||||
[ "$*" ] && echo "$*" | grep -qvE "(^|[[:space:]])$PORT([[:space:]]|$)" && continue
|
||||
printf "${COLOR[${_STATUS[$PORT]}]}%-6s %-8s %5d %-*s %-*s %-*s ${COLOR[NORMAL]}\n" "${_PID[$PORT]}" ${_STATUS[$PORT]} $PORT $USERLEN ${_USER[$PORT]} $DIRLEN ${_DIR[$PORT]} $CMDLEN "${_CMD[$PORT]}"
|
||||
if [ "$logdir" -a "$log" ]
|
||||
then
|
||||
grep '\*\*\*\*' $logdir/$PORT 2>/dev/null
|
||||
grep '\*\*\*\*' $logdir/$PORT 2>/dev/null
|
||||
fi
|
||||
done < $conf
|
||||
done
|
||||
}
|
||||
|
||||
CMD=$1
|
||||
|
||||
Reference in New Issue
Block a user