2017-06-05 73 views
2

我需要在发出命令后在控制台中显示结果。处于打开的cmd.exe当但我无法得到同样的结果与使用subprocess模块返回的变量无法从stdout中获得结果,子流程

例如为:H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject

该命令产生一个加密的证书的值。

到目前为止我已尝试(其中cmd是例如以上):

# checking if output is going to stderr 
out = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) 
# attempt with Popen 
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).communicate()[0] 
# attempt with Popen not using communicate() 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
out = p.stdout.read() 

所有print (out)值是b''

我甚至已经打破了cmd成多个args两个check_output()Popen(),使得它看起来像:["H:/path/to/openssl.exe", "x509 -in H:/path/to/cert.pem -noout -subject"]

我确实有一种替代方法来实现结果,但这需要运行一个包含以下命令的.bat文件:start cmd /k "... > H:/path/to/temp.txt"其中...是此处讨论的命令。这将.exe输出重定向到一个临时文件(出于安全目的),我在将内容读入变量后将其删除。

支持信息:

如果命令的第一部分是run(.exe文件),它会打开自定义控制台该程序。该命令的其余部分在该控制台中执行,然后该控制台关闭。但是,如果整个命令系列在cmd.exe控制台中使用,则输出将显示在该控制台中。因此,为什么使用" "作为.bat的替代方法,因为它将它作为整个命令发布到打开的控制台。

使用subprocess.Popen(["cmd.exe"])C:\Python36>打开控制台,我可以发出有问题的命令,并得到我想要的确切结果。我似乎无法抓住pythonically虽然。但是,subprocess.Popen(["cmd.exe", "H:/path/to/openssl.exe"])不执行第二个命令;打开控制台但不启动.exe控制台。

更新:

我能得到一个结果,但我不喜欢我怎么到了那里。有一个较短的方式来做到以下几点:

p = subprocess.Popen("H:/path/to/openssl.exe", stdin=PIPE, stdout=PIPE) 
# b for byte-type requirement 
p.stdin.write(b"x509 -in H:/path/to/cert.pem -noout -subject") 
p.stdin.close() 
out = p.stdout.read() 

我还可以产生结果:

p = os.popen("start cmd /k H:/path/to/openssl.exe -in H:/path/to/cert.pem -noout -subject")

尝试添加.read()以上,但打印一个空行

+1

一般提示:在'Popen'参数中设置'shell = True'是不安全的。尝试改为将'shlex.split(cmd)'作为第一个参数传递给'Popen'。 – Billy

+0

@比利仍然返回'b'''。我试图找出为什么即使使用分割命令,'Popen()'也没有按照上述“支持信息”中的描述执行第二个命令。 – madeslurpy

+0

@比利更新的问题 – madeslurpy

回答

0

我不习惯在Windows上使用python,但请尝试以下操作。不要使用shell=True,而不是与此CMD尝试:

cmd = ["H:/path/to/openssl.exe", "x509", "-in", "H:/path/to/cert.pem", "-noout", "-subject"] 
+0

应该是一个评论,而不是一个答案。 – Billy

+0

由于'Popen()'没有执行列表中的下一个命令,所以这不起作用 – madeslurpy

0

你试过存储整个命令作为原始字符串,并与外壳传递=真

cmd = r'H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject' p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = p.communicate() print(out[0]) #for std out print(out[1]) # for std err

编辑:这工作了我用标准错误,

print p.communicate()[1]

b'unable to load certificate\r\n3636:error:0D07209B:asn1 encoding routines:ASN1_ get_object:too long:./crypto/asn1/asn1_lib.c:142:\r\n3636:error:0D068066:asn1 en coding routines:ASN1_CHECK_TLEN:bad object header:./crypto/asn1/tasn_dec.c:1281: \r\n3636:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 erro r:./crypto/asn1/tasn_dec.c:380:Type=X509\r\n3636:error:0906700D:PEM routines:PEM _ASN1_read_bio:ASN1 lib:./crypto/pem/pem_oth.c:83:\r\n'

+0

假设你的意思是'print(out [0])'和'print(out [1])'。是的,我都有,并且都是'b'''。这几乎就像命令没有被顺序执行一样。我有一个并行问题发布[这里](https://stackoverflow.com/questions/44371876/why-is-popen-not-executing-next-command) – madeslurpy

+0

对我而言,发生的事情是,我正在有效地运行openssl.exe,传递有效的参数并获得回报。但是它似乎没有进入cmd.exe stdout;它停留在openssl.exe中。我需要基本做'C:\ Users \ Me> H:/path/to/openssl.exe x509 -in H:/path/to/cert.pem -noout -subject'并抓住'stdout';当我运行'Popen()'时,它会产生一个结果,但它被放置在CLI之前的一行而不是'stdout'中。 – madeslurpy