当 PIPE 在命令中时,Python 中使用 subprocess.run 的正确方法
Correct way in Python to use subprocess.run when PIPE is in the command
我正在尝试编写一个 python 脚本来执行以下终端命令:
echo -n | openssl s_client -connect {host}:{port} | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > {host}_{port}.cert
如果我尝试将命令分解为参数以传递给 subprocess.run 它不起作用(有些东西是 运行 但它没有像我希望的那样存储证书。
使用以下语法可以正确执行命令,但我担心这不是最佳实践,我想了解正确的执行方式:
store_certificate_command = f"echo -n | openssl s_client -connect {host}:{port} | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > {host}_{port}.cert"
subprocess.run(store_certificate_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
执行此操作的正确方法是将自己限制在非Python 可执行文件的最小数量。在这种情况下,echo
不是必需的,Python 可以完成 sed
正在做的工作,也可以写入结果文件。一个干净的解决方案是这样的:
import subprocess
with open(f'{host}_{port}.cert', 'wb') as outf,\
subprocess.Popen(['openssl', 's_client', '-connect', f'{host}:{port}'], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc:
for line in proc.stdout:
if b'-BEGIN CERTIFICATE-' in line:
outf.write(line)
break
else:
raise ValueError("BEGIN CERTIFICATE not found in output")
for line in proc.stdout:
outf.write(line)
if b'-END CERTIFICATE-' in line:
break
else:
raise ValueError("END CERTIFICATE not found in output")
我改为使用 subprocess.Popen
,因为它允许您以流方式处理输出(与 shell 管道的工作方式相同),但考虑到相对较小的输出,subprocess.run
也可能工作得很好。 ValueError
不是绝对必要的,但我喜欢把它们放在那里,这样当输出不是你期望的时候你就会失败。
我正在尝试编写一个 python 脚本来执行以下终端命令:
echo -n | openssl s_client -connect {host}:{port} | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > {host}_{port}.cert
如果我尝试将命令分解为参数以传递给 subprocess.run 它不起作用(有些东西是 运行 但它没有像我希望的那样存储证书。
使用以下语法可以正确执行命令,但我担心这不是最佳实践,我想了解正确的执行方式:
store_certificate_command = f"echo -n | openssl s_client -connect {host}:{port} | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > {host}_{port}.cert"
subprocess.run(store_certificate_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
执行此操作的正确方法是将自己限制在非Python 可执行文件的最小数量。在这种情况下,echo
不是必需的,Python 可以完成 sed
正在做的工作,也可以写入结果文件。一个干净的解决方案是这样的:
import subprocess
with open(f'{host}_{port}.cert', 'wb') as outf,\
subprocess.Popen(['openssl', 's_client', '-connect', f'{host}:{port}'], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc:
for line in proc.stdout:
if b'-BEGIN CERTIFICATE-' in line:
outf.write(line)
break
else:
raise ValueError("BEGIN CERTIFICATE not found in output")
for line in proc.stdout:
outf.write(line)
if b'-END CERTIFICATE-' in line:
break
else:
raise ValueError("END CERTIFICATE not found in output")
我改为使用 subprocess.Popen
,因为它允许您以流方式处理输出(与 shell 管道的工作方式相同),但考虑到相对较小的输出,subprocess.run
也可能工作得很好。 ValueError
不是绝对必要的,但我喜欢把它们放在那里,这样当输出不是你期望的时候你就会失败。