我用 Python 编写了一个 GTK GUI 应用程序来调用一个 shell 脚本并将调用参数从 GUI 传递给脚本并在文本窗口中返回脚本结果。
现在我喜欢允许用户从 GUI 中取消正在运行的 shell 脚本。该脚本以 Popen 启动。如果我以普通用户的身份调用它,它工作正常(在下面的代码中标记 sudo=False)。当我使用 sudo 调用脚本时,我无法再取消它。我发现如果我使用 shell=True,人们报告 kill 将不起作用,所以我用 shell=False 对其进行了测试,但它也不起作用。
我将我的问题简化为以下代码片段:
import os
import signal
import subprocess
import time
import sys
import shlex
bashScriptFileName="t.sh"
f = open(bashScriptFileName,'w')
f.write("""#!/bin/bash
on_die()
{
echo "Dying..."
exit 0
}
trap 'on_die' TERM
SEC=0
while true ; do
sleep 1
SEC=$((SEC+1))
echo "I'm PID# $$, and I'm alive for $SEC seconds now!"
done
exit 0""")
f.close()
os.chmod(bashScriptFileName, 0755)
shell=True # flag to enable/disable shell invocation of Popen
sudo=True # flag to invoke command with sudo
if sudo:
commandToExecute='sudo -S '+ bashScriptFileName
else:
commandToExecute='./' + bashScriptFileName
if not shell:
commandToExecute = shlex.split(commandToExecute)
print "Command: %s" % (commandToExecute)
proc = subprocess.Popen(commandToExecute, stdin=subprocess.PIPE, close_fds=False,shell=shell, preexec_fn=os.setsid)
print >> proc.stdin, "secretPassword"
print 'PARENT : Pausing before sending signal to child %s...' % proc.pid
sys.stdout.flush()
time.sleep(5)
print 'PARENT : Signaling child %s' % proc.pid
sys.stdout.flush()
os.killpg(proc.pid, signal.SIGTERM)
time.sleep(3)
print "Done"
实际上,作为普通用户使用 os.kill 取消脚本时,我已经遇到了问题,但后来发现我必须使用 os.setuid 和 killpg 来杀死正在运行的 shell。我是线程新手,这可能只是我对 Linux 线程的一个简单误解......