我想在Mac OS X计算机上使用Python运行以下命令:
openssl enc -aes-128-cbc -K $(echo -n 'blabla1' | xxd -p) -iv blabla2 -in /tmp/clair -nopad -out /tmp/crypte1 -d
以下是我的尝试:
clef = 'blabla1'
iv = 'blabla2'
arguments = ['openssl','enc', '-aes-128-cbc', '-K $(echo -n \'%s\' | xxd -p)' % clef ,'-iv' ,'%s' % iv,'-in', '/tmp/clair','-nopad','-out','/tmp/crypte1','-d']
execute = Popen(arguments, stdout=PIPE)
out, err = execute.communicate()
该命令在终端上工作正常,但我从Python脚本中收到错误:
unknown option '-K $(echo -n 'blabla1' | xxd -p)'
我已经尝试了几种python shell函数变体(例如os.system
),但我在每种情况下都有问题。
答案 0 :(得分:3)
在使用shell时,用户经常认为有很多事情是理所当然的。一些例子是:
${var}
)cmd > out < in
)cmd1 | cmd2
)$(cmd)
)所有这些都是shell在将实际命令传递给系统之前设置的功能。 Python的subprocess
模块不会自动为您执行任何操作,但它确实为您提供了模拟它们的工具。
您已正确地将输出重定向到管道以供Python进程选取。但是,由$(echo -n 'blabla1' | xxd -p)
创建的子shell不会以没有shell的方式处理。有两个简单的解决方法。
快速而肮脏的解决方案是将整个命令行作为字符串传递给subprocess.Popen
并设置shell=True
:
execute = Popen("openssl enc -aes-128-cbc -K $(echo -n 'blabla1' | xxd -p) "
"-iv blabla2 -in /tmp/clair -nopad -out /tmp/crypte1 -d",
shell=True)
这会将字符串传递给shell而不是直接传递给系统,从而使您可以访问shell期望的所有行为。这种方法存在重大安全问题,通常不建议使用。但是,这很容易,它会让你开始。
使用capturing通过subprocess.run
$(... | ...)
的输出直接在代码中实现xxd
的便利性。这个更长,但从长远来看可能更加强大和便携。这当然是我在生产环境中选择的选项:
from subprocess import Popen, run
value = run(['xxd', '-p'], input='blabla1', universal_newlines=True).stdout
execute = Popen(['openssl', 'enc', '-aes-128-cbc', '-K', value,
'-iv', 'blabla2', '-in', '/tmp/clair', '-nopad',
'-out', '/tmp/crypte1', '-d'])
由于您正在设置自己的管道,因此您无需再调用echo
(您从未真正做过,xxd -p <<< 'blabla1'
可以正常工作),并且-K
需要是一个单独的论点。
答案 1 :(得分:0)
subprocess
在参数"
中添加引号"-K $(echo -n 'blabla1' | xxd -p)"
。您可以通过
print(subprocess.list2cmdline(execute.args))
<强>输出:强>
openssl enc -aes-128-cbc "-K $(echo -n 'blabla1' | xxd -p)" -iv blabla2 -in /tmp/clair -nopad -out /tmp/crypte1 -d