3

我对 subprocess.Popen 和我认为是管道的问题有疑问。我有以下代码块,从 cli 运行时 100% 的时间都没有问题:

    p = subprocess.Popen("psexec \\\\" + serverName.get() + " cmd /c \
        ver & \
        echo %USERDOMAIN% & \
        dir /a C:\pagefile.sys | find \"pagefile.sys\" & \
        dir C:\ | find \"bytes free\" & \
        dir D:\ | find \"bytes free\" ", \
        stdin=None, stdout=subprocess.PIPE, stderr=None)

    ### Assign the results from the Popen
    results = p.communicate()[0]
    rc = p.returncode

    print 'results: ' + str(results)
    sys.exit()

输出:

PsExec v1.90 - Execute processes remotely
Copyright (C) 2001-2007 Mark Russinovich
Sysinternals - www.sysinternals.com

The device is not ready.
cmd exited on XXXXXXX with error code 1.

Microsoft Windows XP [Version 5.1.2600]
PROD
02/23/2011  09:37 AM     1,610,612,736 pagefile.sys
              49 Dir(s)  17,104,437,248 bytes free

我已经完成了这个程序,但是一旦我用 py2exe 编译它,它就会挂起或崩溃。我将此问题追溯到 py2exe 不喜欢子进程中未定义的标准输入、输出或错误。然后我修改了我的代码如下:

    p = subprocess.Popen("psexec \\\\" + serverName.get() + " cmd /c \
        ver & \
        echo %USERDOMAIN% & \
        dir /a C:\pagefile.sys | find \"pagefile.sys\" & \
        dir C:\ | find \"bytes free\" & \
        dir D:\ | find \"bytes free\" ", \
        stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    p.stdin.close()

    ### Assign the results from the Popen
    results = p.communicate()[0]
    rc = p.returncode

    print 'results: ' + str(results)
    sys.exit()

这段代码也可以 100% 工作,但是当我打印结果时,它只显示标准 psexec 消息,而不是执行命令的输出。

输出:

results:
PsExec v1.90 - Execute processes remotely
Copyright (C) 2001-2007 Mark Russinovich
Sysinternals - www.sysinternals.com

cmd exited on XXXXXXX with error code 1.

我试图通过在子进程选项中添加 shell=true 来解决这个问题,但是当我这样做时,程序只会挂起 99% 的时间。它实际上会运行 1% 的时间。我注意到,当程序挂起时,如果我进入任务管理器并手动终止 psexec 进程,则会显示所需的输出。这让我发疯,我一直在寻找,但没有找到任何东西。该代码在 WinXP python v2.7 上运行。如果您有任何问题或需要任何其他信息,请告诉我。

挂码:

    p = subprocess.Popen("psexec \\\\" + serverName.get() + " cmd /c \
        ver & \
        echo %USERDOMAIN% & \
        dir /a C:\pagefile.sys | find \"pagefile.sys\" & \
        dir C:\ | find \"bytes free\" & \
        dir D:\ | find \"bytes free\" ", \
        stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)

    p.stdin.close()

    ### Assign the results from the Popen
    results = p.communicate()[0]
    rc = p.returncode

    print 'results:' + str(results)
    sys.exit()

从任务管理器中杀死 psexec.exe 后所需的输出:

results:
PsExec v1.90 - Execute processes remotely
Copyright (C) 2001-2007 Mark Russinovich
Sysinternals - www.sysinternals.com


PROD
02/23/2011  09:37 AM     1,610,612,736 pagefile.sys
              49 Dir(s)  17,102,487,552 bytes free
The device is not ready.
4

3 回答 3

0

尝试使用 -i 运行 psexec 它对我有用

p = subprocess.Popen("psexec " "-i "  . . . 
于 2011-03-09T10:12:28.117 回答
0

我曾经见过这个问题:

  1. 将流量重定向到临时文件似乎是一个可行的解决方案——问题是访问进程输出所需的额外代码——但它是一个稳定的解决方案。问题是获取进程输出所需的额外代码(如果你想在它运行时显示它 - 如果不是,它只是转储一个文件)
  2. 您还可以检查fabric 的本地实现——我没有用它运行 psexec,但所有其他进程都运行良好(除了它不提供超时机制的事实)
于 2011-09-06T19:15:49.223 回答
0

[这应该是评论,但我没有代表发表评论]

我听说 subprocess.PIPE 有很多问题。尝试使标准输入、标准输出和标准错误都指向临时文件。然后你可以使用 p.wait() 而不是communicate()。这似乎工作正常吗?

于 2011-03-07T03:37:03.037 回答