【问题标题】:Python subprocess not executing when daemonized守护进程时Python子进程未执行
【发布时间】:2012-10-15 00:03:02
【问题描述】:

我尝试在父类被守护的方法中执行脚本。

autogamma.sh 是一个需要安装 ImageMagick(并使用转换)的脚本,可以在这里找到:http://www.fmwconcepts.com/imagemagick/autogamma/index.php

import os
import subprocess
import daemon

class MyClass():
    def __init__(self):
        self.myfunc()
    def myfunc(self):
        script = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'autogamma.sh')
        cmd = ('/bin/sh %s -c average /tmp/c.jpg /tmp/d.jpg' % script).split(' ')
        ret = subprocess.Popen(cmd).communicate()

with daemon.DaemonContext():
    process = MyClass()
    process.run()

脚本仅在启动类 MyClass 时正确执行。我认为 env 或类似的东西有问题,但无法得到它。

Rsync、mediainfo、ffprobe 也出现了问题。 使用 Python 2.7.3 和 python-daemon 1.6,在 mac os、centos 5.5、ubuntu 12.04TLS 上测试

【问题讨论】:

  • MyClass 没有run() 方法,所以我认为这是一个错字?

标签: python shell subprocess daemon popen


【解决方案1】:

脚本很短,如果排除读取命令行参数、cmets 和其他颜色模式的代码,它不到 75 行。我会把它转换成 Python。

就像 cmets 建议的那样,最好的方法是使用 ImageMagick 的 python 包装器之一。

您也可以直接致电convert,尽管这可能会很痛苦。这是一个小sn-p的样子:

import subprocess

def image_magick_version():
    output = subprocess.check_output("/usr/local/bin/convert -list configure", shell=True)

    for line in output.split('\n'):
        if line.startswith('LIB_VERSION_NUMBER'):           
            _, version = line.split(' ', 1)
            return tuple(int(i) for i in version.split(','))

im_version = image_magick_version()    
if im_version < (6,7,6,6) or im_version > (6,7,7,7) :
    cspace = "RGB"
else:
    cspace = "sRGB"

if im_version < (6,7,6,7) or im_version > (6,7,7,7):
    setcspace = "-set colorspace RGB"
else:
    setcspace = ""

【讨论】:

  • 我的想法完全正确。并在此过程中放弃使用外壳。链接页面的底部给出了在亮度模式中使用的命令的简短列表。
  • 使用pgmagick wrapper 包可以简化移植过程。
  • 遗憾的是它不是我使用的唯一脚本,所以“翻译”我使用的所有脚本真的很痛苦,Rsync、mediainfo 和许多其他工具也会出现问题。
【解决方案2】:

当我怀疑环境问题时,我会做以下两件事之一:

  1. 使用“env - 不管脚本”在前台运行脚本。这 应该清除环境,并将错误发送到您的终端 标准错误。
  2. 正常运行脚本,但将 stdout 和 stderr 重定向到 /tmp 中的文件:whatever-script > /tmp/output 2>&1

这些使无 tty 的脚本不那么透明。

【讨论】:

  • cmd = ('/bin/sh %s -c average /tmp/c.jpg /tmp/d.jpg' % script) ret = subprocess.Popen(cmd.split(' ') , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, close_fds=False).communicate() fd = open('/tmp/output', 'w').write(str(ret)) 返回 ( '','')
【解决方案3】:

我终于找到了问题所在。这实际上是一个路径问题。在查看库后,我发现了这个有用的参数:

    `working_directory`
        :Default: ``'/'``

        Full path of the working directory to which the process should
        change on daemon start.

        Since a filesystem cannot be unmounted if a process has its
        current working directory on that filesystem, this should either
        be left at default or set to a directory that is a sensible “home
        directory” for the daemon while it is running.

所以我这样设置守护进程:

with daemon.DaemonContext(working_directory='.'):
    process = MyClass()
    process.run()

现在我有了正确的路径,并且我的脚本已正确执行。

【讨论】: