我正在编写一个带有无限循环的python脚本,我在ssh上运行.当某人杀死ssh时,我希望脚本终止.例如:
脚本(script.py):
while True:
# do something
Run Code Online (Sandbox Code Playgroud)
将运行为:
ssh foo ./script.py
Run Code Online (Sandbox Code Playgroud)
当我杀死ssh进程时,我希望另一端的脚本停止运行.
我试过寻找一个封闭的标准输出:
while not sys.stdout.closed:
# do something
Run Code Online (Sandbox Code Playgroud)
但这没用.
我该如何实现这一目标?
编辑:
远程机器是Mac,它在csh中打开程序:
502 29352 ?? 0:00.01 tcsh -c python test.py
502 29354 ?? 0:00.04 python test.py
Run Code Online (Sandbox Code Playgroud)
我正在从python脚本中打开ssh进程,如下所示:
p = Popen(['ssh','foo','./script.py'],stdout=PIPE)
while True:
line = p.stdout.readline()
# etc
Run Code Online (Sandbox Code Playgroud)
编辑
提议的解决方案:
while os.getppid() != 1这似乎在Linux系统上工作,但并没有在远程机器运行OSX时工作.问题是该命令是在csh中启动的(见上文),因此csh的父进程id设置为1,而不是脚本.
stderr这有效,但脚本也在本地运行,我不想打印心跳stderr.
ssh -tt.这确实有效,但有一些奇怪的后果.考虑以下:
remote_script:
#!/usr/bin/env python
import os
import time
import sys
while True:
print time.time()
sys.stdout.flush()
time.sleep(1)
Run Code Online (Sandbox Code Playgroud)
local_script:
#!/usr/bin/env python
from subprocess import Popen, PIPE
import time
p = Popen(['ssh','-tt','user@foo','remote_script'],stdout=PIPE)
while True:
line = p.stdout.readline().strip()
if line:
print line
else:
break
time.sleep(10)
Run Code Online (Sandbox Code Playgroud)
首先,输出真的很奇怪,它似乎不断添加标签或东西:
[user@local ~]$ local_script
1393608642.7
1393608643.71
1393608644.71
Connection to foo closed.
Run Code Online (Sandbox Code Playgroud)
其次,程序在第一次收到时不会退出SIGINT,即我必须按两次Ctrl-C才能杀死local_script.
好的,我有一个解决方案
当ssh连接关闭时,父进程id将从ssh-deamon的pid(处理连接的fork)更改为1.
因此,以下解决了您的问题.
#!/usr/local/bin/python
from time import sleep
import os
#os.getppid() returns parent pid
while (os.getppid() != 1):
sleep(1)
pass
Run Code Online (Sandbox Code Playgroud)
你能否证实这也适合你:)
编辑
我看到你更新了.
这没有经过测试,但为了让这个想法适用于OSX,您可能能够检测到csh更改的过程.以下代码仅说明了一个想法,尚未经过测试.这说我认为它会起作用,但它不会是最优雅的解决方案.如果signals可以找到使用跨平台的解决方案,那将是首选.
def do_stuff():
sleep(1)
if sys.platform == 'darwin':
tcsh_pid = os.getppid()
sshfork_pid = psutil.Process(tcsh_pid).ppid
while (sshfork_pid == psutil.Process(tcsh_pid).ppid)
do_stuff()
elif sys.platform == 'linux':
while (os.getppid() != 1):
sleep(1)
else:
raise Exception("platform not supported")
sys.exit(1)
Run Code Online (Sandbox Code Playgroud)