解决ssh问题不会转发信号

时间:2018-01-24 10:10:27

标签: linux ssh kill

如何解决ssh未转发SIGTERM信号的问题?

我希望print-signal.py终止ssh root@localhost进程终止:

ssh root@localhost /root/print-signal.py

不幸的是,只有ssh进程本身才能获得信号,而不是远程命令(print-signal.py)。远程命令不会终止: - (

由于openssh没有将SIGTERM转发给远程命令,我正在寻找解决办法。

如果print-signal.py ...终止,如何终止ssh root@localhost

这是一个后续问题:Forwarding SIGTERM over ssh

4 个答案:

答案 0 :(得分:3)

免责声明:以下答案不适用于SIGTERM,而是适用于SIGINT。由于疏忽,这不是问题的答案。

您正在观察的问题是由于缺少tty而应该控制您尝试运行的进程。如果没有tty可用,则ssh无法将信号发送到进程。当您对-t命令使用选项ssh时,它将强制伪终端分配,这使得通过ssh发送信号成为可能:

ssh -t root@localhost /root/print-signal.py
  

man ssh -t强制伪终端分配。这可用于在远程机器上执行任意基于屏幕的程序,这可能非常有用,例如,实现菜单服务时。多个-t选项强制tty分配,即使ssh没有本地tty。

Giles on unix.stackexchange给出了一个非常好的解释如何以及为什么。

在这里你可以看到它的工作原理:

[terminal 1]% ssh server ./print_signal.py

在另一个终端上,您看到print_signal.py正在PID=26992sshPID=26991正在username@notty正在[terminal 2]% ssh server ps -f UID PID PPID C STIME TTY TIME CMD username 26991 26989 0 17:06 ? 00:00:00 sshd: username@notty username 26992 26991 0 17:06 ? 00:00:00 python ./print_signal.py username 27347 27345 0 17:07 ? 00:00:00 sshd: username@notty username 27348 27347 0 17:07 ? 00:00:00 ps -f

/sbin/init

使用kill或 CTRL - C 终止ssh进程后,该进程仍处于活动状态,但现在在PPID=1下运行([terminal 2]% ssh server ps -f UID PID PPID C STIME TTY TIME CMD username 26992 1 0 17:06 ? 00:00:00 python ./print_signal.py username 27453 27451 0 17:08 ? 00:00:00 sshd: username@notty username 27454 27453 5 17:08 ? 00:00:00 ps -f

-t

使用[terminal 1]% ssh -t server ./print_signal.py 标志可以很好地杀死另一方的进程:

print_signal.py

在另一个终端上,您看到PID=39277正在sshPID=39276username@pts/10绑定到tty([terminal 2]% ssh server ps -U username -f UID PID PPID C STIME TTY TIME CMD username 39276 39274 0 17:22 ? 00:00:00 sshd: username@pts/10 username 39277 39276 1 17:22 pts/10 00:00:00 python ./print_signal.py username 39317 39314 0 17:22 ? 00:00:00 sshd: username@notty username 39318 39317 5 17:22 ? 00:00:00 ps -U username -f

[terminal 1]% ssh -t server ./print_signal.py
My PID: 39277
^CCaught signal SIGINT (2), exiting.
Connection to server closed

杀死ssh进程后

[terminal 2]% ssh server ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
username 39768 39765  0 17:26 ?        00:00:00 sshd: username@notty
username 39769 39768  6 17:26 ?        00:00:00 ps -U username -f

现在,该流程已在其他服务器上明确终止

{
      "apiVersion":"v1",
      "meta":{
              "pluginVersion":"v3.2.1",
               "isExtruded":true
              },
      "error":{
            "code":"Bad Request",
            "status":400,
            "diagnosticMessage":"invalid barcode type"
              }
}

答案 1 :(得分:1)

我刚刚遇到了这个问题。虽然我还没有找到确切的原因,但是当ssh终止时会发生什么,那就是您的进程已重新初始化为init。您可以告诉进程在父进程去世时询问信号,而不要使用prctl

如果您使用python-prctl,请在/root/print-signal.py上放置以下内容

import signal
import prctl

prctl.setpdeathsig(signal.SIGTERM)

答案 2 :(得分:0)

您可以编写一个包装器,如果父进程是init进程,它将终止:

ssh root@localhost terminate-command-if-parent-is-lost print-signal.py

工具terminate-command-if-parent-is-lost需要执行此操作:

启动argv作为子进程(在此示例中为print-signal.py)。然后它每秒检查其父pid的状态(在Python os.getppid()中)。

如果ppid为1(init进程),则print-signal.py进程已丢失其父进程。这意味着" ssh root @ localhost ..."被终止(或连接已关闭)。

现在terminate-command-if-parent-is-lost终止子流程。

答案 3 :(得分:0)

如果它支持一些内置变量($!),shell可以很容易地帮助你解决这个问题。 这是一个基本的shell解决方案,通过长时间的睡眠替换你的命令。

ssh server '(sleep 100000 & (MID=$!; A=n; while [ "$A" != y ];do echo "i am process $$ want kill "$MID" y/n?"; read A; done; kill -TERM $MID))'

该命令中发送的脚本正在远程主机上运行。