如何终止通过Python启动的无头X服务器?
我想用Python获取网页的截图。为此,我使用的是http://github.com/AdamN/python-webkit2png/。
newArgs = ["xvfb-run", "--server-args=-screen 0, 640x480x24", sys.argv[0]]
for i in range(1, len(sys.argv)):
if sys.argv[i] not in ["-x", "--xvfb"]:
newArgs.append(sys.argv[i])
logging.debug("Executing %s" % " ".join(newArgs))
os.execvp(newArgs[0], newArgs)
这个工具基本上是用正确的参数调用了xvfb-run。但是man xvfb
上说:
注意,上面例子中使用的演示X客户端不会自己退出,所以在xvfb-run退出之前,必须先杀掉它们。
这就意味着,如果整个过程在一个循环中(为了获取多个截图),这个脚本会<????>,除非杀掉X服务器。我该怎么做呢?
1 个回答
5
关于 os.execvp
的文档中提到:
这些函数会执行一个新的程序,替换掉当前的进程;它们不会返回。[..]
所以在调用 os.execvp
之后,程序中的其他语句就不会再执行了。你可能想用 subprocess.Popen
来代替:
subprocess
模块可以让你启动新的进程,连接它们的输入/输出/错误管道,并获取它们的返回代码。这个模块的目的是替代一些旧的模块和函数,比如:
使用 subprocess.Popen
,在虚拟帧缓冲区 X 服务器中运行 xlogo
的代码变成了:
import subprocess
xvfb_args = ['xvfb-run', '--server-args=-screen 0, 640x480x24', 'xlogo']
process = subprocess.Popen(xvfb_args)
现在的问题是 xvfb-run
会在后台启动 Xvfb
进程。调用 process.kill()
并不会杀掉 Xvfb
(至少在我的机器上是这样……)。我尝试了几种方法,到目前为止,唯一有效的办法是:
import os
import signal
import subprocess
SERVER_NUM = 99 # 99 is the default used by xvfb-run; you can leave this out.
xvfb_args = ['xvfb-run', '--server-num=%d' % SERVER_NUM,
'--server-args=-screen 0, 640x480x24', 'xlogo']
subprocess.Popen(xvfb_args)
# ... do whatever you want to do here...
pid = int(open('/tmp/.X%s-lock' % SERVER_NUM).read().strip())
os.kill(pid, signal.SIGINT)
所以这段代码从 /tmp/.X99-lock
中读取 Xvfb
的进程 ID,并向这个进程发送一个中断信号。这个方法有效,但偶尔会出现错误信息(不过我想你可以忽略它)。希望其他人能提供一个更优雅的解决方案。谢谢。