现在有一个程序,除非 Ctrl + C 否则不会停止,我需要一个 Python 程序去跑这个程序(需要跑的这个程序时 Go 写的)
主要代码是
cmd = '%s --config %s ' % (CORE_PROG, CONFIG_FILE_NAME)
try:
proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = json.loads(proc.communicate()[0]) # return the command output
if proc.returncode != 0:
raise Exception('Testing Fail: ' + str(output))
sleep(20)
# Should somehow stop the proc
尝试了很多办法, proc.kill(), proc.terminate(), proc.send_signal(signal.SIGTERM) 都不行
1
xiamx 2016-03-15 01:56:21 +08:00
Control-C 发的是 SIGHUP
|
2
TigerS OP @xiamx 问题应该不是这个,在 python 中 C + C 有一个叫做 CTRL_C_EVENT 的,在 signal 下。但是这些全部都试过了,都不行。
这个是一个 python 的 test 程序,用来 test 我们用 Go 写的一个程序的运行情况,这个 Go 程序的运行是除非主动停止否则不会停止。但是如果不停止, python 就会永远运行下去,连 Outpuut 都没有。现在做法是在我们自己程序上修改一个数值让他运行 30 秒后自动停止,专门用来做 Test 这部分用,但是非常不方便,所以希望能够有一个比较好的解决办法。 |
3
firstway 2016-03-15 07:00:54 +08:00 via Android
go 程序是谁写的?“这个 Go 程序的运行是除非主动停止否则不会停止。”说明这个 go 重载信号处理函数,或者 go 默认一下处理函数。如果你能改可以去改这些函数,甚至可以选另外的信号添加处理函数。
如果你不能修改,可以发信号 9 。这个 go 退出可能不太优雅。 |
4
firstway 2016-03-15 07:05:23 +08:00 via Android
还有一个可能性,就是 go 可能使用 fork 一次或多次,父已经退出,你根本没进程去 kill 。这个可以通过 proc 打印 pid 和 ps 进行对照。
|
5
chinuno 2016-03-15 07:51:49 +08:00
脚本里面调用 killall 应该可以解决了
|
7
auser 2016-03-15 08:11:30 +08:00
def tcpdump_addr_port(addr, port):
def timeout_kill(p): p.kill() logging.debug("Kill tcpdump for timeout({0})".format(PCAP_TIMEOUT_SECONDS)) try: cmdline = "/usr/sbin/tcpdump -nn -i any host {0} and port {1} -c {2}".format(addr, port, PCAP_PACKET_COUNT) logging.debug("begin exec {0}".format(cmdline)) with open(PCAP_TMP_PATH, "w") as file: with open("/dev/null", "w") as fnull: p = Popen(cmdline.split(), stdout=file, stderr=fnull) killproc = threading.Timer(PCAP_TIMEOUT_SECONDS, timeout_kill, [p]) killproc.start() ret = p.wait() if ret >= 0: killproc.cancel() logging.debug("end exec") except Exception as e: logging.error(u"tcpdump error {0}".format(e)) exit(-1) |
9
knightdf 2016-03-15 09:30:03 +08:00
关机
|
10
clino 2016-03-15 09:52:32 +08:00
subprocess.Popen(shell_args, preexec_fn=os.setsid)
具体参考: https://blog.tonyseek.com/post/kill-the-descendants-of-subprocess/ |
11
mengzhuo 2016-03-15 11:09:26 +08:00
哈哈哈,楼上的都没考虑到一下情况。
用 Go 写的程序不会主动退出的原因:程序本就不应该自己退出,但是由于种种原因,楼主没有要到源代码,或者没能力改,所以没办法进行二次修改。 但是楼主只是想要的标准输出日志进行分析呢? |
12
TigerS OP @mengzhuo 输出就是标准的 stdout 输出,然后分析其中的内容,但是在 python 里面,我现有的上面的哪些代码,你不停止那个 Go , Python 就不会往下面跑... 是我哪里写错了么?
@chinuno 这个试过了,也是不行, Windows 下会直接误伤 Python 程序,最终报错 @firstway 查看任务管理器里面看到是程序还在跑,如果手动在任务管理器里面终止就正常,但是手动又达不到自动测试的效果 ===================== 首先谢谢大家回复。 Go 程序是公司原有的程序,由 Team 里面另外一个人负责的,源代码是有,主体程序只是各种数据结构,逻辑和通讯用途。实际使用时候有一个 Termianl 里面的外壳程序,外壳程序调用核心代码的时候写的是当收到用户终止的信息( Ctrl+C )的时候停止,整体的情况给人的感觉就有点像在 Terminal 里面跑 python shell ,你不 Ctrl+C 就会一直在 Python Shell 里面。 另外一个我能说出来的例子有点像 Tor 的 Terminal 版本(接触到的 Termianl 软件实在太少了举不出来什么例子了)在你不终止的时候他会一直运行,只有你 Ctrl+C 的时候才会停止。 现在暂时的做法是将这个外壳包装的程序修改成 30 秒后停止,只能作为测试使用,正式生产环境下肯定是不一样的代码。 现在主要是需要测试生产环境代码,使用 python ,通过运行这个 Go 程序,达到一些测试某些数据的功能。所以需要的是在尽可能不修改 Go 原始代码时候的处理 另外说一下,程序需要跑在 Windows 下...... (晕) 楼上所说的所有办法我全部都试过了,都不能达到很好的效果,要不是 kill() 之后 Go 程序默认是返回 1 (错误状态),要么是根本终止不了。正常情况下 Ctrl+C 之后应该返回 0 的。在 Windows 下试用 CTRL_C_EVENT 直接把 python 也终止了,所以很头疼..... 还有没有什么更好的办法么?? |
13
chinuno 2016-03-15 12:35:30 +08:00
@TigerS 怎么会呢,判断一下当前系统, Linux 的话用 pkill 或者 killall , Windows 用 taskkill ,打开的 go 程序是另外的进程不至于 Python 解释器也一起关掉吧
|
14
Jblue 2016-03-15 12:42:54 +08:00
win 下 kill ,用 taskkill 。
|
15
timonwong 2016-03-15 12:56:01 +08:00 2
其实问题在这里
communicate() 会等待程序退出之后再返回,所以你不要调用 communicate 需要拿结果,写代码取 stdout 和 stderr ,等取完后,写代码结束这个 go 进程 |
17
limbo0 2016-03-15 16:04:48 +08:00
os._exit(0)
|
18
neoblackcap 2016-03-15 17:25:18 +08:00
赞成 @timonwong 的回答
communicate 方法会堵塞了主进程,而且用 communicate 来分析日志显然是错误的用法, communicate 方法返回的结果会存在内存中,很容易爆内存的。 其实我建议是将标准输出重定向到文件,然后读文件来进行分析,最后再发送 SIGINT 来结束程序 |
21
huangxie 2016-03-16 09:45:02 +08:00
except Exception,e:
print "error:",e pass except KeyboardInterrupt,e: print "ctrl+c" pass 这是之前 http://www.quzhuanpan.com 的爬虫的一部分,或许有用 |
22
ry_wang 2016-03-17 16:07:09 +08:00
|
23
DravenJohnson 2016-03-18 23:17:01 +08:00
如果不需要和程序交涉的话,可以考虑 Popen 打开,不 PIPE 输出(除非你需要输出)然后用 win32ui 去 close window ( Only work on Windows )
|