vimer linux kernel 爱好者

有待进一步消化的shell脚本

2022-02-07

目前在看一个deb的service时发现,原来之前自己想要的结果可以通过这样的方式来实现,真的叹为惊叹。这里先记录下来,等到时间充分了,再一点一点吸收。

# the config of ROOT, user must modify it when start srs from other directory,
# it's ok to use the script by command ./etc/init.d/ossrs
ROOT="/usr/local/srs"
APP="./objs/srs"
CONFIG="./conf/srs.conf"
DEFAULT_PID_FILE='./objs/srs.pid'
DEFAULT_LOG_FILE='./objs/srs.log'

########################################################################
# utility functions
########################################################################
RED="\\033[31m"
GREEN="\\033[32m"
YELLOW="\\033[33m"
BLACK="\\033[0m"
POS="\\033[60G"

ok_msg() {
    echo -e "${1}${POS}${BLACK}[${GREEN}  OK  ${BLACK}]"
}

failed_msg() {
    echo -e "${1}${POS}${BLACK}[${RED}FAILED${BLACK}]"
}

# load process info of srs
# @set variable $srs_pid to the process id in srs.pid file.
# @return 0, if process exists; otherwise:
#       1, for pid file not exists.
#       2, for get proecess info by pid failed.
# @set variable $error_msg if error.
# @set variable $pid_file to pid file.
load_process_info() {
    # get pid file
    pid_file=`cd ${ROOT} && cat ${CONFIG} |grep ^pid|awk '{print $2}'|awk -F ';' '{print $1}'`
    if [[ -z $pid_file ]]; then pid_file=${DEFAULT_PID_FILE}; fi
    # get abs path
    pid_dir=`dirname $pid_file`
    pid_file=`(cd ${ROOT}; cd $pid_dir; pwd)`/`basename $pid_file`

    srs_pid=`cat $pid_file 2>/dev/null`
    ret=$?; if [[ 0 -ne $ret ]]; then error_msg="No pid file $pid_file"; return 1; fi

    ps -p ${srs_pid} >/dev/null 2>/dev/null
    ret=$?; if [[ 0 -ne $ret ]]; then error_msg="Process $srs_pid does not exists"; return 2; fi

    return 0;
}

start() {
    # if exists, exit.
    load_process_info
    if [[ 0 -eq $? ]]; then failed_msg "SRS started(pid ${srs_pid}), should not start it again."; return 1; fi

    # not exists, start server
    ok_msg "Starting SRS..."

    # get log file
    log_file=`cd ${ROOT} && cat ${CONFIG} |grep '^srs_log_file'| awk '{print $2}'| awk -F ';' '{print $1}'`
    if [[ -z $log_file ]]; then log_file=${DEFAULT_LOG_FILE}; fi
    # get abs path
    log_dir=`dirname $log_file`
    log_file=`(cd ${ROOT} && cd $log_dir && pwd)`/`basename $log_file`

    # TODO: FIXME: set limit by, for instance, "ulimit -HSn 10000"
    if [[ -z $log_file ]]; then
        (ulimit -c unlimited && cd ${ROOT}; ${APP} -c ${CONFIG} >/dev/null 2>&1)
    else
        (ulimit -c unlimited && cd ${ROOT}; ${APP} -c ${CONFIG} >> $log_file.sys 2>&1)
    fi

    # check again after start server
    for ((i = 0; i < 5; i++)); do
        # sleep a little while, for srs may start then crash.
        sleep 0.1
        load_process_info
        ret=$?; if [[ 0 -ne $ret ]]; then
            failed_msg "SRS start failed";
            failed_msg "see $log_file";
            return $ret;
        fi
    done

    # check whether started.
    load_process_info
    ret=$?; if [[ 0 -eq $ret ]]; then ok_msg "SRS started(pid ${srs_pid})"; return 0; fi

    failed_msg "SRS not started"
    return $ret
}

stop() {
    # not start, exit
    load_process_info
    if [[ 0 -ne $? ]]; then failed_msg "SRS not start."; return 0; fi

    ok_msg "Stopping SRS(pid ${srs_pid})..."

    # process exists, try to kill to stop normally
    for((i=0;i<100;i++)); do
        load_process_info
        if [[ 0 -eq $? ]]; then
            kill -s SIGTERM ${srs_pid} 2>/dev/null
            ret=$?; if [[ 0 -ne $ret ]]; then failed_msg "send signal SIGTERM failed ret=$ret"; return $ret; fi
            sleep 0.3
        else
            ok_msg "SRS stopped by SIGTERM"
            # delete the pid file when stop success.
            rm -f ${pid_file}
            break;
        fi
    done

    # process exists, use kill -9 to force to exit
    load_process_info
    if [[ 0 -eq $? ]]; then
        kill -s SIGKILL ${srs_pid} 2>/dev/null
        ret=$?; if [[ 0 -ne $ret ]]; then failed_msg "send signal SIGKILL failed ret=$ret"; return $ret; fi
        ok_msg "SRS stopped by SIGKILL"
    else
        # delete the pid file when stop success.
        rm -f ${pid_file}
    fi

    sleep 0.1
    return 0
}

# get the status of srs process
# @return 0 if srs is running; otherwise, 1 for stopped.
status() {
    load_process_info
    ret=$?; if [[ 0 -eq $ret ]]; then ok_msg "SRS(pid ${srs_pid}) is running."; return 0; fi

    failed_msg "Error: $error_msg"
    return 1
}

reload() {
    # not start, exit
    load_process_info
    if [[ 0 -ne $? ]]; then failed_msg "SRS not start."; return 0; fi

    ok_msg "Reload SRS(pid ${srs_pid})..."

    # process exists, reload it
    kill -s SIGHUP ${srs_pid} 2>/dev/null
    ret=$?; if [[ 0 -ne $ret ]]; then failed_msg "Reload SRS failed ret=$ret"; return $ret; fi

    load_process_info
    if [[ 0 -ne $? ]]; then failed_msg "SRS reload failed."; return $ret; fi

    ok_msg "SRS reloaded"
    return 0
}

logrotate() {
    # not start, exit
    load_process_info
    if [[ 0 -ne $? ]]; then failed_msg "SRS not start."; return 0; fi

    ok_msg "Reopen log file of SRS(pid ${srs_pid})..."
    kill -s SIGUSR1 ${srs_pid}

    ok_msg "Log rotated"
    return 0
}

grace() {
    # not start, exit
    load_process_info
    if [[ 0 -ne $? ]]; then failed_msg "SRS not start."; return 0; fi

    ok_msg "Gracefully quit for SRS(pid ${srs_pid})..."
    kill -s SIGQUIT ${srs_pid}

    ok_msg "Gracefully quit"
    return 0
}

menu() {
    case "$1" in
        start)
            start
            ;;
        stop)
            stop
            ;;
        restart)
            stop
            start
            ;;
        status)
            status
            ;;
        reload)
            reload
            ;;
        rotate)
            logrotate
            ;;
        grace)
            grace
            ;;
        *)
            echo "Usage: $0 {start|stop|status|restart|reload|rotate|grace}"
            echo "    reload    Apply log file by not restarting SRS"
            echo "    rotate    For log rotate, to send SIGUSR1 to SRS to reopen the log file."
            echo "    grace    For gracefully quit, to send SIGQUIT to SRS."
            return 1
            ;;
    esac
}

menu $1

code=$?
exit ${code}

这是一个可执行的shell,需要在 service启动这个服务。

cat service file

[Unit]
Description=The SRS Media Stream Cluster
After=network.target

[Service]
Type=forking
Restart=always
ExecStart=/etc/init.d/srs start
ExecReload=/etc/init.d/srs reload
ExecStop=/etc/init.d/srs stop

[Install]
WantedBy=multi-user.target

Comments

Content