#!/bin/sh # # BOINC - start and stop the BOINC client daemon on Unix # # Unix start/stop script to run the BOINC client as a daemon at # system startup, as the 'boinc' user (not root!). # # This version should work on unixes that have bash, zsh, or ksh. If # started with another Bourne compatible shell, it will attempt to restart # in bash, zsh, or ksh. # # Metadata for chkconfig and the SUSE equivalent INIT info are included below. # # Usage: boinc { start | stop | status | reload | restart } # ### # chkconfig: 345 98 02 # description: This script starts the local BOINC client as a daemon # For more information about BOINC (the Berkeley Open Infrastructure # for Network Computing) see http://boinc.berkeley.edu # processname: boinc # config: /etc/sysconfig/boinc # ### BEGIN INIT INFO # Provides: boinc # Required-Start: $network # Required-Stop: $network # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Short-Description: This script monitors the BOINC client. # Description: This script starts the local BOINC client as a daemon # For more information about BOINC (the Berkeley Open Infrastructure # for Network Computing) see http://boinc.berkeley.edu ### END INIT INFO # # Eric Myers - 27 July 2004 # Department of Physics and Astronomy, Vassar College, Poughkeepsie NY # Eric Myers # Spy Hill Research, Poughkeepsie, New York # @(#) $Id: boinc,v 1.10 2007/12/27 20:09:09 myers Exp $ # # Modified by Eric Korpela - 11 Apr 2008 ######################################################################## # Defaults, which can be overridden by putting new NAME=value lines # in /etc/sysconfig/boinc-client, /etc/default/boinc-client, # /etc/boinc-client.conf, or the same files under ${sysconfdir} ## These 4 installation dirs set by autoconf. ########################## prefix=`dirname @prefix@/.` exec_prefix=`dirname @exec_prefix@/.` bindir=`dirname @bindir@/.` sysconfdir=`dirname @sysconfdir@/.` ######################################################################## # set the basic PATH PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb/bin export PATH # Find the correct ps to use. On solaris /usr/ucb/ps is the one to use # on everything else, we hope the first one in the path is the right one. if [ -x /usr/ucb/ps ] ; then PS=/usr/ucb/ps else PS=ps fi ######################################################################## # # Figure out if we are running under an acceptable shell # (bash, ksh, zsh) which supports functions. # ######################################################################## SHELLS="bash ksh zsh" # count how many times we've tried to restart TRIES=$2 if [ -z "$TRIES" ] ; then TRIES=0 fi # bash and zsh are easy to test. if [ -z "$BASH_VERSION" -a -z "$ZSH_VERSION" ] ; then # we aren't running under bash or zsh, check for ksh if [ -z "`echo ${ENV} | grep ksh`" ] ; then # still might be ksh. One last shot. if [ -z "`${PS} $$ | tail -1 | grep ksh`" ] ; then # as far as I can tell we aren't in an approved shell TRIES=`expr $TRIES + 1` # have we tried too many times? if [ $TRIES -gt 4 ] ; then echo "ERROR: endless loop discovered in $0 [ERROR]" exit 1 fi for try in $SHELLS ; do ex=`which $try` if [ ! -z "${ex}" -a -x "${ex}" ] ; then if ${ex} $0 $1 $TRIES ; then # it worked, we can exit exit 0 else # it failed for some reason that should have been printed # by the script exit 1 fi fi done # if we got here, we tried everything. echo "ERROR: $0 requires bash, zsh, or ksh to run. [FALIED]" exit 1 fi #if we got here or below, were in an approved shell. fi fi ######################################################################## # Name of user to run as: # BOINCUSER=boinc # Working directory. Could be /home/boinc, /var/lib/boinc, etc.. # The reason I prefer /var/lib/boinc is that this works best for a # cluster of computers where /home/anything might be shared between machines # BOINCDIR=/var/lib/boinc # Name of the client executable. This is the file "boinc" if you # unpacked the download file boinc_M.mm.rr_i686-pc-linux-gnu.sh, # but I like to rename it and put it in a public place. # (Hint: move boincmgr to /usr/local/bin too so anyone can easily use it). # BOINCEXE_NAME=boinc_client BOINCEXE=${bindir}/${BOINCEXE_NAME} BOINCCMD_NAME=boinccmd BOINCCMD=${bindir}/${BOINCCMD_NAME} # Log files (you should rotate these occasionally) # LOGFILE=/var/log/${BOINCEXE_NAME}.log ERRORLOG=/var/log/${BOINCEXE_NAME}_err.log # PID file PIDFILE=/var/run/${BOINCEXE_NAME}.pid # BOINC options: for the command line when running the client. # Be aware that --allow_remote_gui_rpc opens up your machine to the world! # # Add this option if you want to allow boinc manager connections from remote # machines #BOINCOPTS="--allow_remote_gui_rpc" # Add this option if you want to turn off all logging #BOINCOPTS="--daemon" # Add this option if you want to redirect logging to the files stderrdae.txt # and stdoutdae.txt in BOINCDIR rather than LOGFILE and ERRORLOG #BOINCOPTS="--redirectio" # Add this option if you want to run only when no logins from anywhere are # active #BOINCOPTS="--check_all_logins" # The default is no options. BOINCOPTS= # Subsys lock file ... # If there is the subsys directory, then use it ... if [ -d /var/lock/subsys/ ]; then LOCKFILE=/var/lock/subsys/${BOINCEXE_NAME} elif [ -d /var/lock ]; then LOCKFILE=/var/lock/${BOINCEXE_NAME} elif [ -d /var/run ]; then LOCKFILE=/var/run/${BOINCEXE_NAME}.lock fi # su on Linux seems to need this to be set to work properly in a script export TERM=dumb ## # Init script function library. This stuff is Red Hat specific, # but if the functions are not found we create our own simple replacements. # (The idea for replacing the functions comes from OpenAFS. Thanks guys!) if [ -f /etc/rc.d/init.d/functions ] ; then . /etc/rc.d/init.d/functions else if printf "Hello" >/dev/null 2>/dev/null ; then # printf works printcol='printf \033[60G%s' elif echo -en "Hello" >/dev/null 2>/dev/null ; then # echo -en works printcol='echo -en \033[60G' else # no printf make do with echo -n printcol="echo -n .........." fi function echo_success () { $printcol "[OK]" ; } function echo_failure () { $printcol "[FAILED]" ; } function echo_warning () { $printcol "[WARNING]" ; } function killproc() { PID=`local_pidof $1` [ $PID ] && kill $PID } fi # check if we have pidof. If not use ps and grep for the same job. if [ -x /sbin/pidof ] ; then function local_pidof() { pidof -s -x -o $$ -o $PPID -o %PPID $1 } else function local_pidof() { ${PS} xaugww | sed 's/$/ /' | grep "[ /]$1 " | grep -v $$ | grep -v $PPID | grep -v %PPID | grep -v grep | awk '{print $2}' } fi # # Check if we have runuser, since it will never hang waiting for a password. # If we don't have it, use su for the same job. # if [ ! -x /sbin/runuser ] ; then RUNUSER=su else RUNUSER=runuser fi # Some additional places to look for executables # (Should do this after init.d/functions and sysconfig/boinc, which sets PATH) export PATH=${PATH}:${exec_prefix}/sbin:${bindir} ## Look for any local configuration settings which override all above ## Note: ./boinc-client.conf and ./boinc.conf are for testing purposes config_files=" ./boinc-client.conf ./boinc.conf /etc/sysconfig/boinc-client /etc/default/boinc-client /etc/boinc-client.conf ${sysconfdir}/sysconfig/boinc-client ${sysconfdir}/default/boinc-client ${sysconfdir}/boinc-client.conf /etc/sysconfig/boinc /etc/default/boinc /etc/boinc.conf ${sysconfdir}/sysconfig/boinc ${sysconfdir}/default/boinc ${sysconfdir}/boinc.conf none " ## find the correct config file for config_file in $config_files ; do if [ -f ${config_file} ] ; then break; fi done if [ "${config_file}" != "none" ]; then # check whether we are using a deprecated name if [ "x$NOWARNING" != "xyes" -a -z "`echo ${config_file} | grep boinc-client`" ]; then fn=`basename $config_file` dn=`dirname $config_file` newname=`echo $fn | sed 's/boinc/boinc-client/'` echo -n "The filename '${config_file}' is deprecated..." echo_warning echo echo -n "Please rename your config file to '${dn}/${newname}'" echo_warning echo fi # execute the config file. . ${config_file} fi ## Add ${BOINCDIR} to the path, just in case the executables are stored there. export PATH=${PATH}:${BOINCDIR} ## Create the working directory if it doesn't exist: if [ ! -d $BOINCDIR ]; then echo -n "Creating $BOINCDIR " if mkdir -p $BOINCDIR 2>/dev/null ; then if [ -n "$BOINCUSER" ] ; then if chown $BOINCUSER $BOINCDIR ; then echo_success else echo_failure echo exit 7 fi fi else echo_failure echo exit 7 fi fi ## Check what user we are running as: # we can't rely on the existence of "whoami" or "logname", so we'll use ps. USERNOW=`${PS} u $$ | tail -1 | awk '{print $1}'` if [ -z "$BOINCUSER" ] ; then BOINCUSER="${USERNOW}" fi ## Check that BOINCUSER actually exists if [ -z "`grep ^${BOINCUSER}: /etc/passwd`" ] ; then if [ -z "`ypcat passwd 2>/dev/null | grep ^${BOINCUSER}:`" ] ; then if [ -z "`nidump passwd / 2>/dev/null | grep ^${BOINCUSER}:`" ] ; then echo -n ERROR: user ${BOINCUSER} does not exist. echo_failure echo exit 9 fi fi fi # if we are running as root, print a warning. if [ "x$NOWARNING" != "xyes" -a "$BOINCUSER" = "root" ] ; then echo -n WARNING: boinc-client will be running as root echo_warning echo fi # check whether we will be able to write to the BOINC directory if [ "${USERNOW}" = "${BOINCUSER}" ] ; then if [ ! -O ${BOINCDIR} ] ; then echo -n ERROR: $BOINCDIR is not owned by $BOINCUSER. echo_failure echo exit 8 fi elif [ "${USERNOW}" = "root" ] ; then cmd="if test -O ${BOINCDIR} ; then echo success ; fi" if [ -z `su $BOINCUSER -c "$cmd"` ]; then echo -n ERROR: $BOINCDIR is not owned by $BOINCUSER. echo_failure echo exit 8 fi fi ## Locate the executable, either boinc_client, boinc, ## or boinc_M.mm_.... with highest version number ## We only do this if BOINCEXE set above isn't found or is not executable. if [ ! -x $BOINCEXE ]; then BOINCEXE=`$WHICH $BOINCEXE_NAME 2>/dev/null` if [ ! -x "$BOINCEXE" ]; then BOINCEXE=`$WHICH boinc 2>/dev/null` fi fi if [ ! -x "$BOINCEXE" ]; then echo -n "Cannot find an executable for the BOINC client." echo_failure echo exit 2 fi ## boinccmd will probably be in the same place as the boinc_client if [ ! -x $BOINCCMD ]; then BOINCCMD=`$WHICH $BOINCCMD_NAME 2>/dev/null` if [ ! -x "$BOINCCMD" ]; then BOINCCMD=`dirname $BOINCEXE 2>/dev/null`/${BOINCCMD_NAME} fi fi if [ "x$NOWARNING" != "xyes" -a ! -x $BOINCCMD ]; then echo -n "Cannot find the boinccmd executable. Reload will fail." echo_warning echo fi ## Functions: $1 is one of start|stop|status|reload|restart export NOWARNING=yes case "$1" in start) cd $BOINCDIR PID=`local_pidof $BOINCEXE_NAME` if [ -f lockfile -o -f $LOCKFILE ] ; then if [ -z "$PID" ] ; then # a lockfile exists, but boinc_client isn't running /bin/rm -f lockfile $LOCKFILE $PIDFILE 2>&1 > /dev/null else echo -n "Another instance of BOINC is running (PID=${PID})." echo_failure echo exit 1 fi fi if [ ! -d projects ] ; then echo -n "The BOINC client requires initialization." echo_warning echo fi touch ${LOGFILE} ${ERRORLOG} NOCORE="ulimit -c 0 2>&1 >/dev/null" echo -n "Starting BOINC client as a daemon: " if [ "${BOINCUSER}" = "${USERNOW}" ] ; then # I am BOINCUSER. Just start client as me. $NOCORE $BOINCEXE $BOINCOPTS >>$LOGFILE 2>>$ERRORLOG & else chown ${BOINCUSER} ${LOGFILE} ${ERRORLOG} if [ -f gui_rpc_auth.cfg ] ; then chmod g+r gui_rpc_auth.cfg fi ${RUNUSER} - $BOINCUSER -c "$NOCORE ; $BOINCEXE $BOINCOPTS >>$LOGFILE 2>>$ERRORLOG" 2>/dev/null > /dev/null & fi sleep 3 PID=`local_pidof $BOINCEXE_NAME` if [ $PID ]; then echo $PID > $PIDFILE touch $LOCKFILE && echo_success || ( echo_failure ; echo ) fi echo ;; stop) cd $BOINCDIR if [ ! -f $PIDFILE -a ! -f lockfile -a ! -f $LOCKFILE ] ; then echo -n "BOINC is not running (no lockfiles found)." echo_success else echo -n "Stopping BOINC client daemon: " if [ -f $PIDFILE ] ; then PID=`cat $PIDFILE` if [ -n "`${PS} $PID | grep $PID`" ] ; then kill `cat $PIDFILE` sleep 5 fi if [ -z "`${PS} $PID | grep $PID`" ] ; then echo_success else echo_failure echo fi else killproc $BOINCEXE_NAME && echo_success || echo_failure fi # clean up in any case rm -f lockfile 2>/dev/null >/dev/null rm -f $LOCKFILE 2>/dev/null rm -f $PIDFILE 2>/dev/null fi echo ;; reload) if [ ! -f lockfile -a ! -f $LOCKFILE ] ; then echo "BOINC is not running (no lockfiles found) -- starting service." $0 start else $BOINCCMD --read_cc_config >>$LOGFILE 2>>$ERRORLOG && echo_success || $0 restart fi ;; restart) $0 stop $0 start ;; status) PID=`cat $PIDFILE 2>/dev/null` if [ "$PID" != "" ]; then # is it still running? if [ -z "`${PS} $PID | grep $PID`" ]; then # not running. Try the other tests. PID="" fi fi if [ "$PID" == "" ]; then PID=`local_pidof $BOINCEXE_NAME` fi if [ "$PID" == "" ]; then PID=`local_pidof $BOINCEXE` fi if [ "$PID" != "" ]; then echo "BOINC client is running (pid $PID)." else if [ -f $BOINCDIR/lockfile -o -f $LOCKFILE ]; then echo "BOINC is stopped but lockfile(s) exist." exit 2 else echo "BOINC client is stopped." exit 3 fi fi ;; *) echo "Usage: boinc {start|stop|restart|reload|status}" exit 1 esac exit #EOF#