Python。在 Windows 中调用 openssl.exe

Python. Calling openssl.exe in Windows

我有一个 Python 脚本需要在 Windows 中调用 openssl.exe。这是脚本:

import os
import subprocess
#print("Starting startfile method")
#os.startfile('openssl.exe req -out server.csr -newkey:4096 -nodes -keyout server.priv.key -config server.cnf')
#print("Starting Popen method")
#subprocess.Popen('openssl.exe req -out server.csr -newkey rsa:4096 -nodes -keyout server.priv.key -config server.cnf')
#print("Starting run method")
#subprocess.run(['openssl.exe', 'req -out server.csr -newkey rsa:4096 -nodes -keyout server.priv.key -config server.cnf'])
#print("Starting call method")
#subprocess.call('openssl.exe req -out server.csr -newkey rsa:4096 -nodes -keyout server.priv.key -config server.cnf')
#print("Done")

如果我取消注释“os.startfile”行,我会收到找不到文件的错误消息。这就说得通了。 os.startfile 无法处理参数(对吗?)

如果我取消注释 subprocess.Popen 行,openssl 将启动,正常执行,然后挂起。 openssl.exe 进程永远不会退出,因此脚本不会完成。这让我很困惑。

如果我取消注释 subprocess.run 行,那么 openssl.exe 会给我一个错误“req -out... 不是一个有效的命令” 那是因为 openssl.exe 没有吗?不喜欢通过标准输入给出的参数?

如果我取消对 subprocess.call 行的注释,openssl.exe 的行为将完全正常(也就是说,就好像它是来自 Windows 命令行的 运行),并且它退出并允许 Python 脚本继续。

你能帮我理解这些调用外部进程的不同方法之间的区别吗?

startfile 特定于 Windows 并接受参数。这里的错误不是用逗号分隔参数。 (我假设参数本身是正确的)

startfile 将启动一个完全独立于调用它的程序的新文件。所以没有数据可以 returned 到调用程序。 subprocess 在调用程序“内部”运行文件,以便调用程序可以访问 return 代码等数据。

依次更正以下各项:

import os
import subprocess

print("Starting startfile method")
os.startfile('openssl.exe', arguments='req -out server.csr -newkey:4096 -nodes -keyout server.priv.key -config server.cnf')

print("Starting Popen method with shell=True (bad)")
subprocess.Popen('openssl.exe req -out server.csr -newkey rsa:4096 -nodes -keyout server.priv.key -config server.cnf', shell=True)

print("Starting Popen method with shell=False (good)")
subprocess.Popen(['openssl.exe', 'req', '-out', 'server.csr', '-newkey', 'rsa:4096', '-nodes', '-keyout', 'server.priv.key', '-config', 'server.cnf'])

print("Starting run method")
subprocess.run(['openssl.exe', 'req', '-out', 'server.csr', '-newkey', 'rsa:4096', '-nodes', '-keyout', 'server.priv.key', '-config', 'server.cnf'])

print("Starting call method")
subprocess.call(['openssl.exe', 'req', '-out', 'server.csr', '-newkey', 'rsa:4096', '-nodes', '-keyout', 'server.priv.key', '-config', 'server.cnf')

print("Done")

适用于所有这些的规则:

  • 当空格上没有 shell word-splitting 时,不能将多个参数放在一个 space-separated 字符串中;他们需要各自独立。
  • 对于所有 subprocess 系列商品,word-splitting 仅在 shell=True 时提供。但是,添加 shell 会为漏洞和安全漏洞创造空间;只有当你别无选择时才应该这样做。
  • Windows 不同于所有其他主要操作系统,因为它让程序负责解析自己的命令行(因此让每个程序以与任何其他程序不同的、不兼容的方式解析自己的命令行程序工作,它应该选择覆盖标准 C 库的默认行为)。因此,只有 Windows-specific os.startfile 方法允许在单个字符串中传递参数,而无需 shell 或其他负责分隔它们的软件组件。