#!/bin/sh # # description: start/stop/restart an EPICS IOC in a screen session # # Manually set IOC_STARTUP_DIR if xxx.sh will reside somewhere other than softioc #!IOC_STARTUP_DIR=/home/username/epics/ioc/synApps/xxx/iocBoot/iocxxx/softioc # Set EPICS_HOST_ARCH if the env var isn't already set properly for this IOC #!EPICS_HOST_ARCH=linux-x86_64 #!EPICS_HOST_ARCH=linux-x86_64-debug IOC_NAME=xxx # The name of the IOC binary isn't necessarily the same as the name of the IOC IOC_BINARY=xxx # Change YES to NO in the following line to disable screen-PID lookup GET_SCREEN_PID=YES # Commands needed by this script ECHO=echo ID=id PGREP=pgrep SCREEN=screen KILL=kill BASENAME=basename DIRNAME=dirname READLINK=readlink PS=ps # Explicitly define paths to commands if commands aren't found #!ECHO=/bin/echo #!ID=/usr/bin/id #!PGREP=/usr/bin/pgrep #!SCREEN=/usr/bin/screen #!KILL=/bin/kill #!BASENAME=/bin/basename #!DIRNAME=/usr/bin/dirname #!READLINK=/bin/readlink #!PS=/bin/ps ##################################################################### SNAME=${BASH_SOURCE:-$0} SELECTION=$1 if [ -z "$IOC_STARTUP_DIR" ] ; then # If no startup dir is specified, use the directory above the script's directory IOC_STARTUP_DIR=`dirname ${SNAME}`/.. IOC_CMD="../../bin/${EPICS_HOST_ARCH}/${IOC_BINARY} st.cmd.Linux" else IOC_CMD="${IOC_STARTUP_DIR}/../../bin/${EPICS_HOST_ARCH}/${IOC_BINARY} ${IOC_STARTUP_DIR}/st.cmd.Linux" fi #!${ECHO} ${IOC_STARTUP_DIR} ##################################################################### screenpid() { if [ -z ${SCREEN_PID} ] ; then ${ECHO} else ${ECHO} " in a screen session (pid=${SCREEN_PID})" fi } checkpid() { MY_UID=`${ID} -u` # The '\$' is needed in the pgrep pattern to select xxx, but not xxx.sh IOC_PID=`${PGREP} ${IOC_BINARY}\$ -u ${MY_UID}` #!${ECHO} "IOC_PID=${IOC_PID}" if [ "${IOC_PID}" != "" ] ; then # Assume the IOC is down until proven otherwise IOC_DOWN=1 # At least one instance of the IOC binary is running; # Find the binary that is associated with this script/IOC for pid in ${IOC_PID}; do BIN_CWD=`${READLINK} /proc/${pid}/cwd` IOC_CWD=`${READLINK} -f ${IOC_STARTUP_DIR}` if [ "$BIN_CWD" == "$IOC_CWD" ] ; then # The IOC is running; the binary with PID=$pid is the IOC that was run from $IOC_STARTUP_DIR IOC_PID=${pid} IOC_DOWN=0 SCREEN_PID="" if [ "${GET_SCREEN_PID}" == "YES" ] ; then # Get the PID of the parent of the IOC (shell or screen) P_PID=`${PS} -p ${IOC_PID} -o ppid=` # Get the PID of the grandparent of the IOC (sshd, screen, or ???) GP_PID=`${PS} -p ${P_PID} -o ppid=` #!${ECHO} "P_PID=${P_PID}, GP_PID=${GP_PID}" # Get the screen PIDs S_PIDS=`${PGREP} screen` for s_pid in ${S_PIDS} ; do #!${ECHO} ${s_pid} if [ "${s_pid}" == "${P_PID}" ] ; then SCREEN_PID=${s_pid} break fi if [ "${s_pid}" == "${GP_PID}" ] ; then SCREEN_PID=${s_pid} break fi done fi break #else # ${ECHO} "PATHS are different" # ${ECHO} ${BIN_CWD} # ${ECHO} ${IOC_CWD} fi done else # IOC is not running IOC_DOWN=1 fi return ${IOC_DOWN} } start() { if checkpid; then ${ECHO} -n "${IOC_NAME} is already running (pid=${IOC_PID})" screenpid else ${ECHO} "Starting ${IOC_NAME}" cd ${IOC_STARTUP_DIR} # Run xxx inside a screen session ${SCREEN} -dm -S ${IOC_NAME} -h 5000 ${IOC_CMD} fi } stop() { if checkpid; then ${ECHO} "Stopping ${IOC_NAME} (pid=${IOC_PID})" ${KILL} ${IOC_PID} else ${ECHO} "${IOC_NAME} is not running" fi } restart() { stop start } status() { if checkpid; then ${ECHO} -n "${IOC_NAME} is running (pid=${IOC_PID})" screenpid else ${ECHO} "${IOC_NAME} is not running" fi } console() { if checkpid; then ${ECHO} "Connecting to ${IOC_NAME}'s screen session" # The -r flag will only connect if no one is attached to the session #!${SCREEN} -r ${IOC_NAME} # The -x flag will connect even if someone is attached to the session ${SCREEN} -x ${IOC_NAME} else ${ECHO} "${IOC_NAME} is not running" fi } run() { if checkpid; then ${ECHO} -n "${IOC_NAME} is already running (pid=${IOC_PID})" screenpid else ${ECHO} "Starting ${IOC_NAME}" cd ${IOC_STARTUP_DIR} # Run xxx outside of a screen session, which is helpful for debugging ${IOC_CMD} fi } start_medm() { ${IOC_STARTUP_DIR}/../../start_MEDM_xxx } start_caqtdm() { ${IOC_STARTUP_DIR}/../../start_caQtDM_xxx } usage() { ${ECHO} "Usage: $(${BASENAME} ${SNAME}) {start|stop|restart|status|console|run|medm|caqtdm}" } ##################################################################### if [ ! -d ${IOC_STARTUP_DIR} ] ; then ${ECHO} "Error: ${IOC_STARTUP_DIR} doesn't exist." ${ECHO} "IOC_STARTUP_DIR in ${SNAME} needs to be corrected." else case ${SELECTION} in start) start ;; stop | kill) stop ;; restart) restart ;; status) status ;; console) console ;; run) run ;; medm) start_medm ;; caqtdm) start_caqtdm ;; *) usage ;; esac fi