有两台机器,其中一台有一个脚本wait_for_signal.sh
,第二台有一个名为controller.py
的脚本。每个脚本的代码如下所示。
controller.py
的目的是生成一个子进程,该子进程通过 ssh
调用 wait_for_signal.sh
脚本。当 Controller 需要退出时,它需要向运行 wait_for_signal.sh
的远程进程发送中断。
wait_for_signal.sh
#!/bin/bash
trap 'break' SIGINT
trap 'break' SIGHUP
echo "Start loop"
while true; do
sleep 1
done
echo "Script done"
controller.py
import os
import signal
import subprocess
remote_machine = user@ip
remote_path = path/to/script/
remote_proc = subprocess.Popen(['ssh', '-T', remote_machine,
'./' + remote_path + 'wait_for_signal.sh'],
shell=False, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# do other stuff
os.kill(remote_proc.pid, signal.SIGINT)
目前,信号发送给在本地机器上启动 ssh 连接的进程,而不是远程机器。这会导致本地进程停止,但远程进程继续执行。
ssh 是如何工作的,它在停止时向远程机器发送什么类型的信号?如何向通过 ssh 连接启动的远程进程发送适当的信号?
最佳答案
您正在使用 -T
选项调用 ssh
,这意味着它不会为远程 session 分配 PTY(伪 TTY)。在这种情况下,无法通过该 ssh session 向远程进程发送信号。
SSH 协议(protocol)有一个 message to send a signal to the remote process .但是,您可能正在为客户端或服务器或两者使用 OpenSSH,据我所知,OpenSSH 没有实现信号消息。因此 OpenSSH 客户端无法发送消息,OpenSSH 服务器也不会对其进行操作。
有一个SSH extension to send a "break" message OpenSSH 支持。在交互式 session 中,OpenSSH 客户端有一个 escape sequence您可以键入以向服务器发送中断。 OpenSSH 服务器通过向远程 session 的 PTY 发送中断来处理中断消息,而 unix PTY 通常会将中断视为 SIGINT。然而,中断基本上是一个 TTY 概念,这些都不适用于没有 PTY 的远程 session 。
我可以想到两种方法来做你想做的事:
使用
-tt
参数而不是-T
调用ssh
。这将导致 ssh 为远程 session 请求 TTY。通过 TTY 运行远程进程将使其表现得像在交互式运行。终止本地 ssh 进程应该会导致远程进程收到 SIGHUP。将 Ctrl-C 写入本地 ssh 进程的标准输入应该会导致远程进程接收 SIGINT。打开另一个到远程主机的 ssh session 并使用
killall
或其他一些命令来向您想要发出信号的进程发出信号。
关于python - 使用 Python 向远程进程发送信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46333657/