2017-09-21 58 views
0

有兩臺機器,其中一臺具有腳本wait_for_signal.sh,另一臺具有名爲controller.py的腳本。每個腳本的代碼如下所示。使用Python將信號發送到遠程進程

controller.py的用途是生成一個子進程,該子進程通過ssh調用wait_for_signal.sh腳本。當控制器需要退出時,它需要向運行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 = [email protected] 
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連接啓動的遠程進程?

回答

1

您使用-T選項調用ssh,這意味着它不會爲遠程會話分配PTY(僞TTY)。在這種情況下,無法通過該ssh會話發信號通知遠程進程。

SSH協議有一個message to send a signal to the remote process。但是,您可能使用OpenSSH作爲客戶端或服務器,或者同時使用OpenSSH,並且據我所知,OpenSSH不會執行信號消息。所以OpenSSH客戶端不能發送消息,並且OpenSSH服務器不會對其執行操作。

有一個SSH extension to send a "break" message其中由OpenSSH支持。在交互式會話中,OpenSSH客戶端有一個escape sequence,您可以鍵入該值以向服務器發送中斷。 OpenSSH服務器通過向遠程會話的PTY發送中斷來處理中斷消息,並且unix PTYs通常會將中斷視爲SIGINT。然而,休息從根本上說是TTY的概念,並且這些都不適用於沒有PTY的遠程會話。

我能想到的兩種方法可以做到你想要什麼:

  1. 調用ssh-tt參數,而不是-T。這將導致ssh爲遠程會話請求一個TTY。通過TTY運行遠程進程將使它像交互式運行一樣。殺死本地ssh進程應該會導致遠程進程接收SIGHUP。寫一個Ctrl - C到本地ssh進程的標準輸入應該會導致遠程進程接收到一個SIGINT。

  2. 打開另一個ssh會話到遠程主機,並使用killall或其他命令來發信號通知您想要發送的進程。