用于 autossh 的 Bash 初始化脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9296686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:34:31  来源:igfitidea点击:

Bash init script for autossh

bashsshinit

提问by PvdL

I'm trying to create a script that will launch autosshon boot through an init script, but I can't get it to work. I would like to see that it logs all of its actions, since it was not working properly, but that isn't going that well ether. Since I'm not a pro in bashI hope my code isn't horribly embarrassing.

我正在尝试创建一个脚本,该脚本将autossh通过 init 脚本在启动时启动,但我无法让它工作。我想看到它记录了它的所有操作,因为它没有正常工作,但以太坊的情况并不是那么好。由于我不是专业人士,bash我希望我的代码不会太尴尬。

#!/bin/sh
#
# by Patrick van der Leer <[email protected]>
# released under GPL, version 2 or later

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON="/usr/bin/autossh"
DESC="Autossh job"
PIDFOLDER="/var/run/autossh"
PIDFOLDERSSH="$PIDFOLDER/ssh"
REMOTE_USER=""
REMOTE_ADDR=""
LOGFILE="/var/log/autossh.log"

if [ ! -d $PIDFOLDER ] ; then
    mkdir -p $PIDFOLDER
fi

if [ ! -d $PIDFOLDERSSH ] ; then
    mkdir -p $PIDFOLDERSSH
fi

test -f $DAEMON || exit 0

. /lib/lsb/init-functions

PIDFILE="$PIDFOLDER/$REMOTE_USER-$REMOTE_ADDR.pid"
PIDFILESSH="$PIDFOLDERSSH/$REMOTE_USER-$REMOTE_ADDR.pid"

is_running() {
    if [ -f $PIDFILE ]; then
        PID=`cat $PIDFILE`
        if [ -n "$PID" ]; then
            return 0
        else
            return 1
        fi
    else
        return 1
    fi
}

start_autossh() {
    if ! is_running; then
        echo "Starting $DESC"
        export AUTOSSH_FIRST_POLL=10
        export AUTOSSH_POLL=60
        export AUTOSSH_PIDFILE=$PIDFILESSH
        start-stop-daemon --start --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- -M 29000 -i /root/.ssh/id_rsa -X -C -R 2222:localhost:22 $REMOTE_USER@$REMOTE_ADDR >> $LOGFILE 2>&1 &
        sleep 1;
        if ! is_running; then
            echo "$DESC: running @ pid $PID"
        else
            echo 'Something went wrong';
        fi
    else
        echo "$DESC: already running (pid $PID)"
    fi
}

stop_autossh() {
    if is_running; then
        echo "Stopping $DESC"
        start-stop-daemon --stop --pidfile $PIDFILE --signal 15
        if [ -f $PIDSSHFILE ]; then
            PIDSSH=`cat $PIDFILESSH`
            kill $PIDSSH
            rm -f $PIDFILESSH
        fi
    else
        echo "$DESC: not running"
    fi
    [ -f $PIDFILE ] && rm -f $PIDFILE
}

case "" in
    start)
        start_autossh
    ;;
    stop)
        stop_autossh
    ;;
    force-reload|restart)
        stop_autossh
        start_autossh
    ;;
    status)
        if is_running; then
            echo "$DESC: running (pid $PID)"
            exit 0
        else
            echo "$DESC: not running"
            [ -f $PIDFILE ] && exit 1 || exit 3
        fi
    ;;
    log)
        if [ -f $LOGIFLE ]; then
            tail $LOGFILE
        else
            echo "log file '$LOGFILE' does't exist"
        fi
    ;;
    *)
        echo "Usage: 
#!/bin/sh
### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $network $remote_fs $syslog
# Required-Stop:     $network $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: autosshtun
# Description:       Used to launch SSH tunnel with autossh
### END INIT INFO

# Author: Laurent HUBERT <[email protected]>
#
# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="AUTOSSH Tunnel"
NAME=autosshtun
DAEMON=/usr/lib/autossh/autossh
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

CONN_PORT=22
SSH_TUNNEL_KEY_PATH=/root/.ssh/id-rsa
SSH_USERNAME=user
SSH_SERVER=server.domain.tld
ENTRY_PORT=1122
EXIT_PORT=22

ENV_COMMAND=/usr/bin/env 
ENV_OPTIONS="AUTOSSH_PIDFILE=$PIDFILE"
SSH_COMMAND_OPTIONS="-p $CONN_PORT -i $SSH_TUNNEL_KEY_PATH $SSH_USERNAME@$SSH_SERVER"
OPEN_TUNNEL_OPTIONS="-T -N -R $ENTRY_PORT:localhost:$EXIT_PORT"

AUTOSSH_OPTION="-M 0" 

DAEMON_ARGS="$AUTOSSH_OPTION $SSH_COMMAND_OPTIONS $OPEN_TUNNEL_OPTIONS"

is_running() {
    if [ -f $PIDFILE ]; then
        PID=`cat $PIDFILE`
        if [ -n "$PID" ]; then
            return 0
        else
            return 1
        fi
    else
        return 1
    fi
}
#
# Function that starts the daemon/service
#
do_start()
{
    QUIET="--quiet"
    if ! is_running; then
        start-stop-daemon --background --start $QUIET --name $NAME \
            --exec $ENV_COMMAND -- $ENV_OPTIONS $DAEMON $DAEMON_ARGS
        retval=$?
        sleep 1

        if [ $retval -gt 0 ]; then
            return $retval
        else
            sleep 1
            start-stop-daemon --stop $QUIET --pidfile $PIDFILE \
            --test --exec $DAEMON > /dev/null || return 2
        fi
    else
        return 1
    fi
}

#
# Function that stops the daemon/service
#
do_stop()
{
    # 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 --retry=TERM/10/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=TERM/10/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}


case "" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    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" "$NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  status)
    status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
    ;;
  restart)
    log_daemon_msg "Restarting $DESC" "$NAME"
    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
    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
    exit 3
    ;;
esac
{start|stop|restart|force-reload|status|log}" exit 3 ;; esac exit 0

回答by Jan Hudec

Shell will print all statements just before it executes them if you set the xoption. Either:

如果您设置了该x选项,Shell 将在执行它们之前打印所有语句。任何一个:

  • Run the script as /bin/sh -x script.
  • Change the #!line to #!/bin/sh -x.
  • Do set -xat the beginning of the script.
  • 将脚本作为/bin/sh -x script.
  • 将该#!行更改为#!/bin/sh -x
  • 不要set -x在脚本的开始。

Obviously the first will set it for that one run, the other two will set it for each run.

显然,第一个将为该一次运行设置它,其他两个将为每次运行设置它。



Checking man page of start-stop-daemon(8)it seems you are using it wrong. You should notbackground start-stop-daemonwith &, you should instead tell start-stop-daemonto background the executed process using --backgroundoption. The documentation for --make-pidfileeven says it should not be expected to work except together with --backgroundoption.

检查start-stop-daemon(8) 的手册页,您似乎使用错误。你应该没有背景start-stop-daemon&,则应该告诉start-stop-daemon背景使用执行过程--background选项。--make-pidfileeven的文档说它不应该被期望工作,除非与--background选项一起使用。

You also should be redirecting the start-stop-dameon's output, it's only output of the process you need redirected. start-stop-daemonwill redirect it to /dev/nullIIRC, but I don't see a way to override this. You might have to create a wrapper that will execit with appropriate redirections and use that in --startasoption, unless you manage to tell autosshto log into a file directly.

您还应该重定向 start-stop-dameon 的输出,它只是您需要重定向的进程的输出。start-stop-daemon将它重定向到/dev/nullIIRC,但我看不到覆盖它的方法。您可能必须创建一个包装器,exec它将使用适当的重定向并在--startas选项中使用它,除非您设法告诉autossh直接登录到文件。

回答by lauhub

The script below runs one and only one autossh process when invoked.

下面的脚本在调用时只运行一个 autossh 进程。

##代码##