Linux 如何设置后台 ssh 隧道的自动(重新)启动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6758897/
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-08-05 05:08:59  来源:igfitidea点击:

How to set up an automatic (re)start of a background ssh tunnel

linuxbatch-filessh

提问by Marvin

I am a beginner user of linux, and also quite newbie at ssh and tunnels.

我是 linux 的初学者用户,也是 ssh 和隧道的新手。

Anyway, my goal is to maintain a ssh tunnel open in background.

无论如何,我的目标是在后台保持 ssh 隧道打开。

In order to do that, I wrote the following batch that I then added into crontab (the batch is automatically processed every 5 minutes during workdays and from 8am to 9pm). I read in some other thread in stackoverflow that one should use autossh that will ensure the ssh will always be ok through a recurrent check. So did I....

为了做到这一点,我编写了以下批处理,然后将其添加到 crontab 中(该批处理在工作日和从上午 8 点到晚上 9 点每 5 分钟自动处理一次)。我在 stackoverflow 的其他一些线程中读到,应该使用 autossh,这将确保 ssh 通过定期检查始终正常。我也是....

#!/bin/bash
LOGFILE="/root/Tunnel/logBatchRestart.log"
NOW="$(date +%d/%m/%Y' - '%H:%M)" # date & time of log

if ! ps ax | grep ssh | grep tunnelToto &> /dev/null
then
    echo "[$NOW] ssh tunnel not running : restarting it" >> $LOGFILE
    autossh -f -N -L pppp:tunnelToto:nnnnn [email protected] -p qqqq
    if ! ps ax | grep ssh | grep toto &> /dev/null
    then
            echo "[$NOW] failed starting tunnel" >> $LOGFILE
    else
            echo "[$NOW] restart successfull" >> $LOGFILE
    fi
fi

My problem is that sometimes the tunnel stops working, although every thing looks ok (ps ax | grep ssh > the result shows the two expected tasks : autossh main task and the ssh tunnel itself). I actually know about the problem cause the tunnel is used by a third party software that triggers an error as soon as the tunnel is no more responding.

我的问题是有时隧道会停止工作,尽管一切看起来都很好(ps ax | grep ssh > 结果显示了两个预期任务:autossh 主任务和 ssh 隧道本身)。我实际上知道这个问题,因为隧道被第三方软件使用,一旦隧道不再响应,就会触发错误。

SO I am wondering how I should improve my batch in order It will be able to check the tunnel and restart it if it happens to be dead. I saw some ideas in there, but it was concluded by the "autossh" hint... which I already use. Thus, I am out of ideas... If any of you have, I'd gladly have a look at them!

所以我想知道我应该如何改进我的批次以便它能够检查隧道并在它碰巧死了时重新启动它。我在那里看到了一些想法,但它是由“autossh”提示得出的……我已经使用了。因此,我没有想法......如果你们中的任何人有,我很乐意看看它们!

Thanks for taking interest in my question, and for your (maybe) suggestions!

感谢您对我的问题感兴趣,以及您(可能)的建议!

采纳答案by powerMicha

Instead of checking the sshprocess with psyou can do the following trick

您可以执行以下技巧,而不是检查ssh过程ps

create script, that does the following and add it to your crontab via crontab -e

创建脚本,执行以下操作并将其添加到您的 crontab 通过 crontab -e

#!/bin/sh

REMOTEUSER=username
REMOTEHOST=remotehost 

SSH_REMOTEPORT=22
SSH_LOCALPORT=10022

TUNNEL_REMOTEPORT=8080
TUNNEL_LOCALPORT=8080

createTunnel() {
    /usr/bin/ssh -f -N  -L$SSH_LOCALPORT:$REMOTEHOST:SSH_REMOTEPORT -L$TUNNEL_LOCALPORT:$REMOTEHOST:TUNNEL_REMOTEPORT $REMOTEUSER@$REMOTEHOST
    if [[ $? -eq 0 ]]; then
        echo Tunnel to $REMOTEHOST created successfully
    else
        echo An error occurred creating a tunnel to $REMOTEHOST RC was $?
    fi
}

## Run the 'ls' command remotely.  If it returns non-zero, then create a new connection
/usr/bin/ssh -p $SSH_LOCALPORT $REMOTEUSER@localhost ls >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
    echo Creating new tunnel connection
    createTunnel
fi

In fact, this script will open two ports

其实这个脚本会打开两个端口

  • port 22 which will be used to check if the tunnel is still alive
  • port 8080 which is the port you might want to use
  • 端口 22 将用于检查隧道是否还活着
  • 端口 8080 这是您可能想要使用的端口

Please check and send me further questions via comments

请检查并通过评论向我发送更多问题

回答by Marvin

(I add this as an answer since there is not enough room for it un a comment)

(我将此添加为答案,因为没有足够的空间来评论)

Ok, I managed to make the batch run to launch the ssh tunnel (I had to specify my hostname instead of localhost in order it could be triggered) :

好的,我设法使批处理运行以启动 ssh 隧道(我必须指定我的主机名而不是 localhost 才能触发它):

#!/bin/bash

LOGFILE="/root/Tunnel/logBatchRedemarrage.log"
NOW="$(date +%d/%m/%Y' - '%H:%M)" # date et heure du log


REMOTEUSER=username
REMOTEHOST=remoteHost

SSH_REMOTEPORT=22
SSH_LOCALPORT=10022

TUNNEL_REMOTEPORT=12081
TUNNEL_SPECIFIC_REMOTE_PORT=22223
TUNNEL_LOCALPORT=8082

createTunnel() {
    /usr/bin/ssh -f -N  -L$SSH_LOCALPORT:$REMOTEHOST:$SSH_REMOTEPORT -L$TUNNEL_LOCALPORT:$REMOTEHOST:$TUNNEL_REMOTEPORT [email protected] -p $TUNNEL_SPECIFIC_REMOTE_PORT
    if [[ $? -eq 0 ]]; then
        echo [$NOW] Tunnel to $REMOTEHOST created successfully >> $LOGFILE
    else
        echo [$NOW] An error occurred creating a tunnel to $REMOTEHOST RC was $? >> $LOGFILE
    fi
    }

## Run the 'ls' command remotely.  If it returns non-zero, then create a new connection
/usr/bin/ssh -p $SSH_LOCALPORT [email protected] ls >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
    echo [$NOW] Creating new tunnel connection >> $LOGFILE
    createTunnel
fi

However, I got some immediate message (below) when the tunnel is running and when cron tries to lauch the batch again... sounds like it cannot listen to it. Also since I need some time to get a proof , I can't say yet it will successfully restart if the tunnel is out.

但是,当隧道正在运行并且 cron 尝试再次启动批处理时,我收到了一些即时消息(如下所示)......听起来它听不到它。此外,由于我需要一些时间来获得证明,所以我还不能说如果隧道关闭它会成功重启。

Here's the response to the second start of the batch.

这是对批处理第二次启动的响应。

bind: Address already in use channel_setup_fwd_listener: cannot listen to port: 10022 bind: Address already in use channel_setup_fwd_listener: cannot listen to port: 8082 Could not request local forwarding.

绑定:地址已在使用 channel_setup_fwd_listener:无法侦听端口:10022 绑定:地址已在使用中 channel_setup_fwd_listener:无法侦听端口:8082 无法请求本地转发。

回答by rxw

You can use netcat to test the connection and open it if necessary:

您可以使用 netcat 测试连接并在必要时打开它:

while sleep 3; do nc -z localhost 3333 >/dev/null || ssh -NfL 3333:lg:5432 rene@lg; done