我是 Linux 的初学者,而且对 ssh 和隧道也很新手。
无论如何,我的目标是在后台保持 ssh 隧道打开。
为了做到这一点,我编写了以下批处理,然后将其添加到 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
我的问题是,有时隧道会停止工作,尽管一切看起来都正常(ps ax | grep ssh > 结果显示两个预期任务:autossh 主任务和 ssh 隧道本身)。我实际上知道这个问题,因为隧道由第三方软件使用,一旦隧道不再响应,就会触发错误。
所以我想知道我应该如何改进我的批次,以便它能够检查隧道并在它碰巧死掉时重新启动它。我在there中看到了一些想法,但它是由我已经使用的“autossh”提示得出的结论。因此,我没有主意了......如果你们中有人有的话,我很乐意看看它们!
感谢您对我的问题感兴趣,以及您(也许)的建议!
您可以执行以下技巧,而不是使用
ssh
检查 ps
进程
创建脚本,执行以下操作并通过
crontab -e
将其添加到您的 crontab
#!/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
事实上,这个脚本会打开两个端口
请检查并通过评论向我发送更多问题
您不需要为此手工制作 bash 脚本!
systemd
,它为启动/停止/重新启动服务提供了坚实的支持,并具有可配置的条件和超时。
systemd
服务单元:sudo vim /etc/systemd/system/ssh-tunnel.service
[Unit]
Description=ssh
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=5
StartLimitBurst=1
[Service]
# NOTE: you MUST start ssh *without!* the -f (forking) switch,
# so that systemd can monitor it and detect when the tunnel goes down
Type=simple
# forward *local* port 80 to port 8088 on the remote host
ExecStart=ssh [email protected] -N -R 8088:localhost:80
# send an exit signal to the SSH master process that controls the tunnel
ExecStop=ssh arh -O exit -R 8088:localhost:80
# see: https://www.freedesktop.org/software/systemd/man/systemd.service.html#TimeoutStartSec=
TimeoutStartSec=10
TimeoutStopSec=10
Restart=always
RestartSec=10
# TODO: set the user name here; root will be used if unset
# make sure the user has the correct ssh key or otherwise
# explicitly pass the key with `ssh -i /path/to/key/id_rsa
User=my-user-name
# TODO: for debugging only; remove once you get the service working
StandardOutput=console
[Install]
WantedBy=multi-user.target
# make service start on every boot (after network is up)
sudo systemctl enable ssh-tunnel
sudo systemctl start ssh-tunnel
systemctl status ssh-tunnel
StartLimitIntervalSec
配置统计服务启动的时间间隔。如果某个服务在此时间间隔内启动超过StartLimitBurst
次,则不允许再启动。 TimeoutStartSec
配置 systemd
在认为服务处于失败状态之前等待服务启动的最长时间。
使用上述配置,如果 SSH 隧道出现故障,例如由于临时网络故障,
systemd
将等待 10 秒,然后重新启动隧道。
这种方法可靠、可配置,并实现与其他答案或实用程序(如 autossh)中给出的脚本相同的结果,但采用可与任何其他工具一起使用的通用方式。
这里的关键是在 foreground 模式下启动 SSH(即不要使用
-fn
开关将其发送到后台),以便 systemd
可以监控服务是否仍然存在并在失败时重新启动它。
(我将其添加为答案,因为评论中没有足够的空间)
好吧,我设法运行批处理来启动 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
但是,当隧道运行时以及当 cron 尝试再次启动批处理时,我立即收到一些消息(如下)......听起来它无法收听它。另外,由于我需要一些时间来获得证明,所以我还不能说如果隧道消失它会成功重新启动。
这是对第二批启动的响应。
bind:地址已在使用中channel_setup_fwd_listener:无法监听 到端口:10022 绑定:地址已在使用中 Channel_setup_fwd_listener:无法侦听端口:8082 无法 请求本地转发。