如何调试 systemd 下的旧 init.d 脚本?

如何调试 systemd 下的旧 init.d 脚本?

我无法从脚本中获取任何输出。

systemd 仅打印:

sinopia.service: control process exited, code=exited status=203
Failed to start LSB: starts the sinopia web server.

我甚至无法直接启动它(sudo sh -c '/etc/init.d/sinopia start')。它说它是通过“systemctl”启动的。

如何调试?

### BEGIN INIT INFO
# Provides:          sinopia
# Required-Start:    $local_fs $remote_fs $network $syslog $named
# Required-Stop:     $local_fs $remote_fs $network $syslog $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the sinopia web server
# Description:       starts sinopia using start-stop-daemon
### END INIT INFO

#Set the path env variable
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

#Installed? "whereis nvm"
#Example: IF node ONLY (NO nvm) 
DAEMON=/usr/bin/nodejs

#This becomes the name of the pid and log file.
APPNAME="sinopia"
DESC="sinopia: a private npm repository"

PIDFILE="/var/run/$APPNAME.pid"
LOGFILE="/var/log/$APPNAME.log"

#Set the working directory. The command below will first "cd" into this directory before executing nvm
APPROOT="/path/to/working/directory/for/sinopia/"

#Format is "filename ARGS"
#Example: DAEMON_ARGS="server.js ADDITIONAL-ARGS-HERE"
DAEMON_ARGS="/usr/local/bin/sinopia"

#Example: IF node ONLY (NO nvm): 
NODECMD="cd $APPROOT && exec $DAEMON $DAEMON_ARGS >>$LOGFILE 2>&1"

#Set the user:group id that this process will be run under
NODEUSER=root:root

# Creates the logfile with ownership of NODEUSER
if [ ! -e "$LOGFILE" ]; then
        touch "$LOGFILE"
fi

# always make logfile have this user's permissions to write, else the app won't start if a logfile exists with someone else's permissions
chown $NODEUSER "$LOGFILE"

test -x $DAEMON || exit 0

. /lib/init/vars.sh
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --chuid $NODEUSER --pidfile $PIDFILE --background --exec $DAEMON --test > /dev/null \
        || { [ "$VERBOSE" != no ] && log_daemon_msg  "  --->  Daemon already running $DESC" "pid=$PIDFILE"; return 1; }
    start-stop-daemon --start --quiet --chuid $NODEUSER --make-pidfile --pidfile $PIDFILE --background --exec $DAEMON --startas /bin/sh -- -c "$NODECMD" \
        || { [ "$VERBOSE" != no ] && log_daemon_msg  "  --->  could not start $DESC" "pid=$PIDFILE"; return 2; }
    [ "$VERBOSE" != no ] && log_daemon_msg  "  --->  started $DESC" "pid=$PIDFILE"
}

#
# Function that stops the daemon/service
#
do_stop()
{

    # If the $PID file exists
    # Detect child processes (nvm is the parent with a single node child)
    if [ -f $PIDFILE ];
    then

        # FUTURE improvement ??? --- until we all move to systemd?
        #http://stackoverflow.com/questions/1570262/shell-get-exit-code-of-background-process

        # readin the parent PID
        read PPID <$PIDFILE

        # graceful exit
        pkill -TERM -P $PPID

        sleep 1
    fi

    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --chuid $NODEUSER --retry=TERM/30/KILL/5 --pidfile $PIDFILE
    RETVAL="$?"

    sleep 1
    return "$RETVAL"
}

#
# Rotate log files
#
do_rotate() {
    start-stop-daemon --stop --signal USR1 --quiet --chuid $NODEUSER --pidfile $PIDFILE --name $APPNAME
    return 0
}

case "$1" in
    start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "pid=$PIDFILE"
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
    stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "pid=$PIDFILE"
        do_stop
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
    restart)
        log_daemon_msg "Restarting $DESC" "pid=$PIDFILE"

        # Future
        # Check configuration before stopping the node-zazzy instance
        #if ! test_nginx_config; then
        #   log_end_msg 1 # Configuration error
        #   exit 0
        #fi

        do_stop
        case "$?" in
            0|1)
                do_start
                case "$?" in
                    0) log_end_msg 0 ;;
                    1) log_end_msg 1 ;; # Old process is still running
                    *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
            *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
    status)
        status_of_proc -p $PIDFILE "$DAEMON" "$APPNAME" && exit 0 || exit $?
        ;;
    rotate)
        log_daemon_msg "Re-opening $DESC log files" "$APPNAME"
        do_rotate
        log_end_msg $?
        ;;
    *)
        echo "Usage: $APPNAME {start|stop|restart|rotate}" >&2
        exit 3
        ;;
esac

答案1

不得不猜测#!/bin/sh是缺少了什么。然后记录到日志文件以发现 VERBOSE 变量使用被破坏了。

#!/bin/sh

### BEGIN INIT INFO
# Provides:          sinopia
# Required-Start:    $local_fs $remote_fs $network $syslog $named
# Required-Stop:     $local_fs $remote_fs $network $syslog $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the sinopia web server
# Description:       starts sinopia using start-stop-daemon
### END INIT INFO

#Set the path env variable
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

#Installed? "whereis nvm"
#Example: IF node ONLY (NO nvm) 
DAEMON=/usr/bin/nodejs

#This becomes the name of the pid and log file.
APPNAME="sinopia"
DESC="sinopia: a private npm repository"

PIDFILE="/var/run/$APPNAME.pid"
LOGFILE="/var/log/$APPNAME.log"

#Set the working directory. The command below will first "cd" into this directory before executing nvm
APPROOT="/home/myuser/sinopia/"

#Format is "filename ARGS"
#Example: DAEMON_ARGS="server.js ADDITIONAL-ARGS-HERE"
DAEMON_ARGS="/usr/local/bin/sinopia"

#Example: IF node ONLY (NO nvm): 
NODECMD="cd $APPROOT && exec $DAEMON $DAEMON_ARGS >>$LOGFILE 2>&1"

#Set the user:group id that this process will be run under
NODEUSER=root:root

# Creates the logfile with ownership of NODEUSER
if [ ! -e "$LOGFILE" ]; then
        touch "$LOGFILE"
fi

# always make logfile have this user's permissions to write, else the app won't start if a logfile exists with someone else's permissions
chown $NODEUSER "$LOGFILE"

test -x $DAEMON || exit 0

. /lib/init/vars.sh
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --chuid $NODEUSER --pidfile $PIDFILE --background --exec $DAEMON --test > /dev/null \
        || { [ "$VERBOSE" != no ] && log_daemon_msg  "  --->  Daemon already running $DESC" "pid=$PIDFILE"; return 1; }
    start-stop-daemon --start --quiet --chuid $NODEUSER --make-pidfile --pidfile $PIDFILE --background --exec $DAEMON --startas /bin/sh -- -c "$NODECMD" \
        || { [ "$VERBOSE" != no ] && log_daemon_msg  "  --->  could not start $DESC" "pid=$PIDFILE"; return 2; }
    [ "$VERBOSE" != no ] && log_daemon_msg  "  --->  started $DESC" "pid=$PIDFILE"
}

#
# Function that stops the daemon/service
#
do_stop()
{

    # If the $PID file exists
    # Detect child processes (nvm is the parent with a single node child)
    if [ -f $PIDFILE ];
    then

        # FUTURE improvement ??? --- until we all move to systemd?
        #http://stackoverflow.com/questions/1570262/shell-get-exit-code-of-background-process

        # readin the parent PID
        read PPID <$PIDFILE

        # graceful exit
        pkill -TERM -P $PPID

        sleep 1
    fi

    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --chuid $NODEUSER --retry=TERM/30/KILL/5 --pidfile $PIDFILE
    RETVAL="$?"

    sleep 1
    return "$RETVAL"
}

#
# Rotate log files
#
do_rotate() {
    start-stop-daemon --stop --signal USR1 --quiet --chuid $NODEUSER --pidfile $PIDFILE --name $APPNAME
    return 0
}

case "$1" in
    start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "pid=$PIDFILE"
        do_start
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0; exit 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
    stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "pid=$PIDFILE"
        do_stop
        case "$?" in
            0|1) [ "$VERBOSE" != no ] && log_end_msg 0; exit 0 ;;
            2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
    restart)
        log_daemon_msg "Restarting $DESC" "pid=$PIDFILE"

        # Future
        # Check configuration before stopping the node-zazzy instance
        #if ! test_nginx_config; then
        #   log_end_msg 1 # Configuration error
        #   exit 0
        #fi

        do_stop
        case "$?" in
            0|1)
                do_start
                case "$?" in
                    0) log_end_msg 0 ;;
                    1) log_end_msg 1 ;; # Old process is still running
                    *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
            *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
    status)
        status_of_proc -p $PIDFILE "$DAEMON" "$APPNAME" && exit 0 || exit $?
        ;;
    rotate)
        log_daemon_msg "Re-opening $DESC log files" "$APPNAME"
        do_rotate
        log_end_msg $?
        ;;
    *)
        echo "Usage: $APPNAME {start|stop|restart|rotate}" >&2
        exit 3
        ;;
esac

相关内容