Python subprocess.call() 与 psexec 似乎无法配合使用

1 投票
1 回答
1362 浏览
提问于 2025-04-18 18:06

我在用 subprocess.call() 和 psexec 执行远程进程时遇到了一些问题。我使用以下语法来远程执行进程:

def execute(hosts):
    ''' Using psexec, execute the script on the list of hosts '''
    successes = []

    wd = r'c:\\'
    file = r'c:\\script.exe'
    for host in hosts:
        res = subprocess.call(shlex.split(r'psexec \\%s -e -s -d -w %s %s ' % (host,wd,file)), stdin=None, stdout=None, stderr=None)
        if res == 0:
           successes.append(host)   
        else:
            logging.warning("Error executing script on host %s with error code %d" % (host, res))

    print shlex.split(r'psexec \\%s -e -s -d -w %s %s ' % (hosts[0],wd,file))
    return successes 

正如你所看到的,作为故障排除的一部分,我打印了 shlex.split() 的输出,以确保它是我想要的。这条打印语句的输出是:

['psexec', '\\HOSTNAME', '-e', '-s', '-d', '-w', 'c:\\', 'c:\\script.exe']

这正是我所期待的。不幸的是,当我运行它时,出现了一个错误,提示:

PsExec could not start \GN-WRK-02:
The system cannot find the file specified.

紧接着,我用程序应该用的确切语法运行 psexec 命令(根据 shlex.split() 的输出判断),结果完全正常。我的语法是:

psexec \\HOSTNAME -e -s -d -w c:\\ c:\\script.exe

有没有人知道为什么这不工作?如果有帮助的话,执行函数是通过 multiprocessing 的 map() 函数在两个或三个主机列表上调用的。

任何帮助都非常感谢!谢谢!

1 个回答

2

你在主机名前面的 \\ 双斜杠其实只算一个斜杠;它是重复的,用来表示转义这个斜杠。

你可以在 shlex.split() 的输出中看到这一点:

['psexec', '\\HOSTNAME', '-e, '-s', '-d', '-w', 'c:\\', 'c:\\script.exe']

注意,在主机名之前的 \\ 其实就是两个反斜杠,就像在 c:\\ 文件名中一样。 如果你只打印这个值,你会发现开头的反斜杠其实只是一个字符:

>>> print '\\HOSTNAME'
\HOSTNAME
>>> '\\HOSTNAME'[0]
'\\'
>>> '\\HOSTNAME'[1]
'H'

这是因为 shlex.split() 是一个 POSIX 工具,而不是 Windows 工具,它也把原始字符串中的 \\ 视为转义;如果你在使用这个工具,就需要再把斜杠加倍:

shlex.split(r'psexec \\\\%s -e -s -d -w %s %s ' % (host,wd,file))

另一种选择可能是 禁用 POSIX 模式,但我不太确定这在 Windows 上会有什么影响:

shlex.split(r'psexec \\%s -e -s -d -w %s %s ' % (host,wd,file), posix=False)

撰写回答