当我中断ssh本身时,如何使ssh杀死远程进程?

26

在bash脚本中,我通过ssh在远程机器上执行命令。如果用户通过按下Ctrl + C来终止脚本,它只会停止脚本 - 甚至不会停止ssh客户端。此外,即使我杀死ssh客户端,远程命令仍在运行...

如何让bash在按下Ctrl + c时杀死本地ssh客户端和远程命令调用?

一个简单的脚本:

#/bin/bash
ssh -n -x root@db-host 'mysqldump db' -r file.sql
5个回答

24

最终我找到了这样的解决方案:

#/bin/bash
ssh -t -x root@db-host 'mysqldump db' -r file.sql

因此,我使用“-t”而不是“-n”。 删除“-n”,或者使用不同的用户(非root用户)没有帮助。

4
当你的ssh会话结束时,你的shell会收到一个SIGHUP(挂断信号)。你需要确保它将其发送到从中启动的所有进程。对于bash,尝试使用shopt -s huponexit; your_command。这可能不起作用,因为man页面说huponexit仅适用于交互式shell。
我记得在我的集群上运行用户作业时遇到过这个问题,无论他们是否必须使用nohup(以获得你想要的相反行为),但我在bash man页面中找不到任何关于子进程默认忽略SIGHUP的内容。希望huponexit能解决问题。(你可以将该shopt放在你的.bashrc中,而不是在命令行中。)
然而,你的ssh -t应该可以工作,因为当连接关闭时,从终端读取的内容将得到EOF或错误,这会使大多数程序退出。

2
你知道你传递给ssh的选项是做什么用的吗?我猜想你不知道。-n选项将输入重定向到/dev/null,因此在远程主机上运行的进程可能无法看到来自Ctrl-C的SIGINT信号。
现在,让我们谈谈允许远程root登录有多么糟糕的主意:
这是一个非常糟糕的主意。查看如何设置ssh密钥以获取一些建议,以便通过ssh安全地管理远程进程执行。如果您需要以特权远程运行某些内容,则可能需要使用包含嵌入式命令的ssh公钥和通过sudo以root身份运行的脚本的解决方案。

1
trap "some_command" SIGINT

当您按下Ctrl+C时,将在本地执行some_commandhelp trap将告诉您有关其其他选项的信息。

关于ssh问题,我对ssh不是很了解。也许您可以使其调用ssh -n -x root@db-host 'killall mysqldump'而不是some_command来终止远程命令?


0
如果您不想要求使用"ssh -t"怎么办(对于像我这样健忘的人)?
我偶然发现查看父PID,因为从启动会话中的CTRL/C导致远程进程上的ssh启动进程退出,尽管其子进程继续。例如,这是我的脚本,它在远程服务器上。
#!/bin/bash
Answer=(Alive Dead)
Index=0
while [ ${Index} -eq 0 ]; do
  if ! kill -0 ${PPID} 2> /dev/null ; then Index=1; fi
  echo "Parent PID ${PPID} is ${Answer[$Index]} at $(date +%Y%m%d%H%M%S%Z)" > ~/NowTime.txt
  sleep 1
done

我使用"ssh remote_server ./test_script.sh"来调用它。 在远程服务器上,"watch cat ~/NowTime.txt"显示文件中的时间戳增加,并声明父进程仍在运行; 一旦我在启动进程中按下CTRL/C,远程服务器上的脚本会注意到其父进程已经死亡,然后退出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接