【问题标题】:start a service with popen : command not stopping使用 popen 启动服务:命令不停止
【发布时间】:2015-08-12 13:24:40
【问题描述】:

我尝试在 python 中创建一个备份脚本并使用 popen 启动、停止服务... 停止服务正在工作,但不幸的是启动服务工作,但阻止了其余的执行,脚本停留在那里,为什么?

似乎以某种方式与 httpd 服务相关联... :-(

程序配置元素类似于“service;httpd;start”或“/etc/init.d/myprog;start”

class execute(actions):
    def __init__(self,config,section,logger):
        self.name="execute"
        actions.__init__(self,config,section,logger)

    def process(self):
        try:
            program=self.config.get(self.section,"program").split(";")
            self.logger.debug("program=%s" % program)
            p = subprocess.Popen(program, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout, stderr = p.communicate()

            if stdout:
                self.logger.info(stdout)
            if stderr:
                self.logger.error(stderr)

            return p.returncode

        except Exception:
            self.logger.exception(Exception)

【问题讨论】:

  • 嗯,当你在命令行中输入service myprog start 会发生什么?您是否必须等到在另一个终端输入service myprog stop
  • 不,很快,大约 5 秒
  • 我也想知道为什么 stdout 只在命令结束时显示...我在运行时看不到它

标签: python python-2.7 subprocess popen


【解决方案1】:

您还必须将标准输入作为管道打开,然后关闭它(如果您使用 read() 和 write() 而不是communicate())。

p = subprocess.Popen(..., stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.close()
print "Stdout:", p.stdout.read()
print "Stderr:", p.stderr.read()

如果它不起作用,并且你真的不需要任何检查,只需在调用 Popen 后关闭所有管道,什么会导致程序执行和分离 来自管道。

警告:如果程序不自行终止,这将使程序作为守护程序运行。

完成此操作后,您可以调用 wait() 来查看它是否也会阻塞。并使用退出代码检查最终错误。

它们并不多。服务是否启动。有时甚至返回该服务正在运行,但服务崩溃。

要检查服务脚本是否仍在运行,但没有阻塞,请使用:

if p.poll()==None: print "Still running"

否则,poll() 返回退出代码。

这可以很好地启动和停止服务:

from subprocess import Popen, PIPE
service = "brltty"
p = Popen(["service", service, "start"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Note: using sequence uses shell=0
stdout, stderr = p.communicate()
print "Stdout:", stdout
print "Stderr:", stderr

不要忘记将开始更改为停止 :D :D :D

【讨论】:

  • 事实上我正在尝试停止和启动正常的 linux 服务...启动需要大约 30 秒,停止大约 15 秒...但是脚本即使在 10 分钟后也没有完成,当一段时间以来,一切都已经再次运行......如果我在没有管道的情况下运行,我不知道命令是否顺利,或者是否有错误
  • 是的,我看到了你的尝试。如果您真的必须通过管道进行挖掘,请不要使用communicate()。使用 p.stdout.read() 或 p.stderr.read()。正如我所说,你将无法推断出太多,甚至不会收到任何错误,无论它们在那里。额外的问题是服务脚本也会启动服务。所以它是调用守护进程的脚本。有时它可能会使事情变得混乱。照我说的做,有效果!
  • 抱歉,在communicate() 之前关闭标准输入会导致IO 错误。我忘了。但是在没有关闭任何东西的情况下停止工作,但是当 stdin 作为 PIPE 打开时。
  • 你最后的代码和平和我的有什么区别?我不确定?
  • 它有 stdin=PIPE。正如我在答案的第一行中所写。这会导致communicate() 在调用它后关闭标准输入。这反过来又确保程序被终止。如果没有它,服务脚本似乎会因为某种原因而阻塞。这对我有用,对你有用吗?
【解决方案2】:

p.communicate() 的调用等待进程终止。

参考:subprocess documentation

与进程交互:将数据发送到标准输入。从标准输出读取数据并 stderr,直到到达文件结尾。 等待进程终止。 可选的输入参数应该是一个要发送给孩子的字符串 进程,或者 None,如果不应该向孩子发送数据。

您可以尝试改用p.poll()。此方法不等待进程终止。

【讨论】:

  • 我仍然不明白为什么 service myprog stop 有效,而 service myprog start 无效?为什么进程没有终止?
  • 我缺少在启动/停止时调用的实际命令。我的猜测是 stop 会终止服务并立即返回,因此在这种情况下您没有观察到等待p.communicate。然而,服务启动会调用一个长时间运行的活动,p.communicate 等待此活动完成。
  • 不是我的问题,“服务 xxx 启动”过程大约持续了几秒钟,但 p.communicate 一直卡住......我不解释为什么
猜你喜欢
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 2016-11-13
  • 1970-01-01
  • 2019-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多