用于在循环中探测ssh连接的Linux脚本,并在连接后启动log命令

时间:2017-11-13 08:17:55

标签: linux bash shell ssh

我有一台主机重启或重新连接了很多次。 我希望在我的开发机器上运行一个脚本,该脚本不断尝试登录到该机器,如果成功运行特定命令(拖尾日志数据)。 编辑:为了澄清,连接需要保持打开状态。 log命令保持拖尾,直到我手动停止。

到目前为止我有什么

#!/bin/bash

IP=192.168.178.1

if (("$#" >= 1))
then
  IP=$1
fi

LOOP=1

trap 'echo "stopping"; LOOP=0' INT

while (( $LOOP==1 ))
do
if ping -c1 $IP
then
  echo "Host $IP reached" 
  sshpass -p 'password' ssh -o ConnectTimeout=10 -q user@$IP '<command would go here>'
else
  echo "Host $IP unreachable"
fi
sleep 1

done

实际上并未使用LOOP标志。该脚本通过CTRL-C结束。 现在,如果我不在ssh之后添加要执行的命令,而是手动启动日志输出,这就行了。在断开连接时,脚本会继续探测连接,并在主机再次可用后重新登录。 此外,当我从主机断开连接(CTRL-D)时,如果没有足够快地按下CTRL-C,脚本将立即重新登录到主机。 当我在ssh之后添加要执行的命令时,循环被破坏。所以按下(CTRL-C)不仅会停止日志,还会断开并终止开发机器上的脚本。

我想我必须在某处产生另一个shell或类似的东西?

1)我希望脚本继续探测,登录并完全自动运行命令,并在连接中断时回退到探测状态。 2)我希望能够停止主机上的日志(CTRL-C),从而回退到已登录的ssh连接以手动使用它。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

也许最好的“修复”方法就是修复要求。

有问题的部分是数字“2)”。 问题出在SIGINT的工作原理上。

触发后,会将其发送到与您的终端相关的当前控制组。大多数情况下,这是shell,任何进程都是从那里开始的。使用更现代的shell(您似乎使用bash),shell管理控制组,以便在后台启动的程序(通过分配不同的控制组)。

在您的情况下,ssh在前台启动(从前台执行的脚本),因此它将接收中断,将其转发到远程并在远程终止时立即终止。到那时脚本shell已经处理了它的信号处理程序(由trap指定),它将退出循环并自行终止。

因此,正如您所看到的,您已经超载CTRL-C意味着两件事:

  • 终止监控脚本
  • 终止远程命令并继续为远程端指定的任何内容。

如果放弃第一个效果(或者至少使其更明确),你可能会更接近你想要的东西。然后,调用远程端上不会终止自身而只是尾部命令的脚本将是步骤。在这种情况下,您可能需要使用-t开启ssh来获取一个终端,以便稍后允许正常 shell操作。

这样,不允许仅用CTRL-C终止远程端。您总是需要退出将要运行的远程shell。

此类远程脚本的本质可能如下所示:

tail command
shell

当然,您需要添加shell或编码样式所需的任何部分。

另一种方法是保持当前远程命令被终止,并为跨越shell的中断情况添加另一个ssh调用以供交互使用。但在这种情况下,“CTRL-C也无法完全终止辅修。”

要实现此目的,您可以尝试使用监视脚本更改活动中断处理程序,以便在远程端返回时立即触发终止。但是,这将导致用户能够识别远程命令终止(并且控制已返回到本地脚本)和正确的中断处理程序之间的竞争条件。您可能能够充分降低风险,首先激活新的trap处理程序,然后回显事实并添加睡眠以允许用户做出反应。

答案 1 :(得分:0)

不确定你在说什么。

此外,您应该在/ etc / ssh / sshd_config中禁用PasswordAuthentication并通过将家庭计算机的公钥添加到`〜/ .ssh / authorized_keys

来记录

! / bin / sh的

while [ true ];
do
    RESPONSE=`ssh -i /home/user/.ssh/id_host user@$IP 'tail /home/user/log.txt'`

    echo $RESPONSE

    sleep 10
done