使用两个字符串输入运行子进程命令

时间:2016-08-01 22:33:53

标签: python bash variables subprocess

我正在尝试使用CA捆绑文件验证证书。原始的Bash命令采用两个这样的文件参数;

openssl verify -CAfile ca-ssl.ca cert-ssl.crt

我试图弄清楚如何在python子进程中运行上面的命令,同时将ca-ssl.ca和cert-ssl.crt作为变量字符串(而不是文件)。

如果我在bash中使用变量(而不是文件)运行命令,那么这将起作用;

ca_value=$(<ca-ssl.ca)
cert_value=$(<cert-ssl.crt)

openssl verify -CAfile <(echo "$ca_value") <(echo "$cert_value")

但是,我正在努力弄清楚如何使用Python来完成上述操作,最好不需要使用shell=True。我尝试了以下但不起作用,而是为openssl打印'help'命令;

certificate = ''' cert string '''
ca_bundle = ''' ca bundle string '''

def ca_valid(cert, ca):
    ca_validation = subprocess.Popen(['openssl', 'verify', '-CAfile', ca, cert], stdin=subprocess.PIPE, stdout=subprocess.PIPE,  bufsize=1)
    ca_validation_output = ca_validation.communicate()[0].strip()
    ca_validation.wait()

ca_valid(certificate, ca_bundle)

任何关于我需要进一步研究的指导/线索都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

最后Bash进程替换--keyFile提供文件路径作为<(...)的参数。

您需要创建一个辅助函数来创建此功能,因为Python没有任何运算符允许您将管道数据内联到文件中并显示其路径:

openssl

其中import subprocess def validate_ca(cert, ca): with filearg(ca) as ca_path, filearg(cert) as cert_path: ca_validation = subprocess.Popen( ['openssl', 'verify', '-CAfile', ca_path, cert_path], stdout=subprocess.PIPE, ) return ca_validation.communicate()[0].strip() 是一个上下文管理器,它使用您想要的文本创建一个命名的临时文件,关闭它,将路径交给您,然后在filearg范围结束后删除它。

with

访问此临时文件(如子进程)的任何内容都需要在上下文管理器中工作。

顺便说一下,import os import tempfile from contextlib import contextmanager @contextmanger def filearg(txt): with tempfile.NamedTemporaryFile('w', delete=False) as fh: fh.write(txt) try: yield fh.name finally: os.remove(fh.name) 是多余的,因为Popen.wait(self)等待终止。

答案 1 :(得分:-2)

如果您想使用流程替换,您将 使用shell=True。这是不可避免的。 <(...)进程替换语法是bash语法;你只需要将bash调用服务来解析并执行这样的代码。

此外,您必须确保调用bash,而不是sh。在某些系统上sh可能引用旧的Bourne shell(而不是Bourne-again shell bash),在这种情况下,进程替换肯定不起作用。在某些系统sh将调用bash,但进程替换仍然不起作用,因为在名称sh下调用bash shell时会进入称为POSIX模式的东西。以下是bash手册页的一些摘录:

  

...

     

INVOCATION

     

...当调用sh时,bash在读取启动文件后进入posix模式。 ....

     

...

     

另见

     

...

     

http://tiswww.case.edu/~chet/bash/POSIX - posix模式的描述

     

...

从以上网站链接:

  
      
  1. 无法使用流程替换。
  2.   

/bin/sh似乎是python中的默认shell,无论您是使用os.system()还是subprocess.Popen()。因此,如果要指定完整路径,则必须指定参数executable='bash'executable='/bin/bash'

这对我有用:

subprocess.Popen('printf \'argument: "%s"\\n\' verify -CAfile <(echo ca_value) <(echo cert_value);',executable='bash',shell=True).wait();
## argument: "verify"
## argument: "-CAfile"
## argument: "/dev/fd/63"
## argument: "/dev/fd/62"
## 0

以下是如何实际嵌入变量中的字符串值:

bashEsc = lambda s: "'"+s.replace("'","'\\''")+"'";
ca_value = 'x';
cert_value = 'y';
cmd = 'printf \'argument: "%%s"\\n\' verify -CAfile <(echo %s) <(echo %s);'%(bashEsc(ca_value),bashEsc(cert_value));
subprocess.Popen(cmd,executable='bash',shell=True).wait();
## argument: "verify"
## argument: "-CAfile"
## argument: "/dev/fd/63"
## argument: "/dev/fd/62"
## 0