首页 > 代码库 > 非root用户执行开机启动服务脚 本

非root用户执行开机启动服务脚 本

一、需求

centos6下面添加开机服务,例如开机启动supervisor服务,然后supervisor会负责拉起配置的进程,从而实现各种服务的开机重启。

二、原理需求

在centos6下面主要通过在/etc/init.d/下面添加服务脚本和chkconfig命令来完成添加启动服务

  • 添加服务的启停脚本
    如果需要开机启动服务,或者通过service命令控制服务,必须在/etc/init.d/下面有对应服务的启停脚本,如果我们的服务为supervisor,那么在/etc/init.d/下面对应的启停脚本就是supervisor,且具有执行权限。启停脚本个格式一般都是固定的,比如包括start、stop等函数,来用来对服务进行启动/关闭

   如

#!/bin/bash
#
# supervisord   This scripts turns supervisord on
#
# Author:       Mike McGrath <mmcgrath@redhat.com> (based off yumupdatesd)
#               Jason Koppe <jkoppe@indeed.com> adjusted to read sysconfig,
#                   use supervisord tools to start/stop, conditionally wait
#                   for child processes to shutdown, and startup later
#               Mikhail Mingalev <mingalevme@gmail.com> Merged
#                   redhat-init-jkoppe and redhat-sysconfig-jkoppe, and
#                   made the script "simple customizable".
#               Brendan Maguire <maguire.brendan@gmail.com> Added OPTIONS to
#                   SUPERVISORCTL status call
#
# chkconfig:    345 83 04
#
# description:  supervisor is a process control utility.  It has a web based
#               xmlrpc interface as well as a few other nifty features.
#               Script was originally written by Jason Koppe <jkoppe@indeed.com>.
#
# usage:rename this script to ‘supervisor‘ and put it to directory /etc/init.d/

# source function library
. /etc/rc.d/init.d/functions

# service strips all environment variables but TERM, PATH and LANG,
# so we need export those variables explicitly.
# see http://unix.stackexchange.com/questions/44370/how-to-make-unix-service-see-environment-variables
export HOSTNAME
export USER=hadoop2

# hadoop‘s environment variables
. /home/hadoop2/.bashrc

SUPERVISORD=/usr/bin/supervisord
SUPERVISORCTL=/usr/bin/supervisorctl

PIDFILE=/tmp/supervisord.pid
LOCKFILE=/tmp/supervisord

OPTIONS="-c /usr/local/supervisor/supervisord.conf"

# unset this variable if you don‘t care to wait for child processes to shutdown before removing the $LOCKFILE-lock
WAIT_FOR_SUBPROCESSES=yes

# remove this if you manage number of open files in some other fashion
ulimit -n 96000

RETVAL=0

running_pid()
{
    # Check if a given process pid‘s cmdline matches a given name
    pid=$1
    name=$2
    [ -z "$pid" ] && return 1
    [ ! -d /proc/$pid ] && return 1
    (cat /proc/$pid/cmdline | tr "\000" "\n"|grep -q $name) || return 1
    return 0
}

running()
{
    # Check if the process is running looking at /proc
    # (works for all users)

    # No pidfile, probably no daemon present
    [ ! -f "$PIDFILE" ] && return 1
    # Obtain the pid and check it against the binary name
    pid=`cat $PIDFILE`
    running_pid $pid $SUPERVISORD || return 1
    return 0
}

is_root()
{
    current_user=`whoami`
    if [ "x"$current_user == "xroot" ];then
       echo "current_user is:"$current_user
       return 0
    elif [ "x"$USER == "xroot" ];then
       echo "USER is:"$USER
       return 0
    else
       return 1
    fi
}

start() {
        echo "Starting supervisord: "
        if running ; then
            echo "ALREADY STARTED"
		    return 1
		fi

        if  is_root ;then
                # start supervisord with options from sysconfig (stuff like -c)
                su hadoop2 -c "$SUPERVISORD $OPTIONS"

                # show initial startup status
                su hadoop2 -c "$SUPERVISORCTL $OPTIONS status"

                # only create the subsyslock if we created the PIDFILE
                su hadoop2 -c "[ -e $PIDFILE ] && touch $LOCKFILE"
        else
                # start supervisord with options from sysconfig (stuff like -c)
                $SUPERVISORD $OPTIONS

                # show initial startup status
                $SUPERVISORCTL $OPTIONS status

                # only create the subsyslock if we created the PIDFILE
                [ -e $PIDFILE ] && touch $LOCKFILE
        fi

}

stop() {
        echo -n "Stopping supervisord: "
        if is_root ;then
           su hadoop2 -c "$SUPERVISORCTL $OPTIONS shutdown"
        else
           $SUPERVISORCTL $OPTIONS shutdown
        fi
	if [ -n "$WAIT_FOR_SUBPROCESSES" ]; then
            echo "Waiting roughly 60 seconds for $PIDFILE to be removed after child processes exit"
            for sleep in  2 2 2 2 4 4 4 4 8 8 8 8 last; do
                if [ ! -e $PIDFILE ] ; then
                    echo "Supervisord exited as expected in under $total_sleep seconds"
                    break
                else
                    if [[ $sleep -eq "last" ]] ; then
                        echo "Supervisord still working on shutting down. We‘ve waited roughly 60 seconds, we‘ll let it do its thing from here"
                        return 1
                    else
                        sleep $sleep
                        total_sleep=$(( $total_sleep + $sleep ))
                    fi

                fi
            done
        fi

        # always remove the subsys. We might have waited a while, but just remove it at this point.
        rm -f $LOCKFILE
}

restart() {
        stop
        start
}

case "$1" in
    start)
        start
        RETVAL=$?
        ;;
    stop)
        stop
        RETVAL=$?
        ;;
    restart|force-reload)
        restart
        RETVAL=$?
        ;;
    reload)
        $SUPERVISORCTL $OPTIONS reload
        RETVAL=$?
        ;;
    condrestart)
        [ -f $LOCKFILE ] && restart
        RETVAL=$?
        ;;
    status)
        $SUPERVISORCTL $OPTIONS status
        if running ; then
            RETVAL=0
        else
            RETVAL=1
        fi
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
        exit 1
esac

exit $RETVAL


一些坑

  • 开机启动的用户身份是root,可我们需要是其他用户身份,比如hadoop启动服务
    使用su user -c "cmd_here" 来执行服务启动,可以用你希望的用户身份启动服务

  • 环境变量读取不到,例如JAVA_HOME等,造成服务启动不成功
    这主要是service系统在执行时,会strip掉除TERM、PATH等以外所以环境变量。解决的办法是在启停服务脚本中export需要的环境变量

  • 添加或启动service时,提示No such file or directory
    可能是你在windows下面编辑文件,然后上传到linux,因为windows的许多编辑器会在末尾多加换行。详细解决方案,看这里

    1、运行检查

cat -v /etc/init.d/your_init_script

   2.解决

sed -i -e ‘s/\r//g‘ /etc/init.d/your_init_script


非root用户执行开机启动服务脚 本