在Linux中使用subprocess和管道命令

3
我想要在Python脚本中运行下一个命令:
strings <FILE NAME> | grep "Version = <VERSION STRING>" > /dev/null

我需要保存以下脚本逻辑的命令返回码和命令输出。

目前,我使用了以下代码:

     strings_out = subprocess.Popen(('strings', file), stdout=subprocess.PIPE)
     grep_output = subprocess.check_output(('grep', "Version = " + version_string), stdin=strings_out.stdout)
     strings_out.wait()

我遇到错误了

subprocess.CalledProcessError: Command '('grep', 'Version = <VERSION STRING>')' returned non-zero exit status 1

我猜测 check_output 内存用尽了。

我的 subprocess 使用有什么问题吗?


没有问题,只是它没有找到任何匹配。 - alani
你实际上想做什么?只是检查是否存在匹配吗?(你不需要使用grep,你可以直接在Python中轻松检查“strings”的输出。) - alani
希望您在上述代码的第一行后面提到 strings_out.wait()。有可能 grep 命令在第一个命令完成之前就已经运行,例如如果 strings 命令的输出很大。 - Swadhikar
@alaniwi,你说的“直接在Python中检查字符串输出”是什么意思? - BaruchLi
@BaruchLi 您可以将 strings 命令的输出读入到 Python 中,并使用 Python 正则表达式(或者对于简单的子字符串搜索,甚至只需使用 in)来测试您要查找的版本字符串是否存在。 - alani
显示剩余2条评论
3个回答

0

check_output 的非零退出状态意味着 bash 命令出现了问题 - 我不认为你的内存用完了。

在我自己的测试中,我发现如果我给 grep 一个存在于文件中的字符串,我会得到一个正确的输出,而你的代码也是如此(我没有使用 Version,因为我不知道你有哪些输入文件,但除此之外,一切都差不多)。然而,如果我 grep 一个不存在的字符串,我会得到和你一样的错误。

也许你正在运行它在一个字符串不输出任何实例的文件上 "Version = " + version_string。如果你在一个循环中,只需要一个文件没有正确的字符串就会出现错误。

另外,如果你计划完成这条线:strings <FILE NAME> | grep "Version = <VERSION STRING>" > /dev/null,你将把输出导向 /dev/null。在这种情况下,你将看不到 grep 的输出。


0

正如@samsonjm所提到的,每个成功运行的bash命令都有退出代码= 0。这意味着grep命令失败了。此外,没有关于内存不足错误的线索。

我怀疑strings命令的输入文件很大,因此可能需要更长时间才能返回结果。因此,我怀疑应立即在上面的第一行之后调用string_out.wait()指令,以将输入从stdin提供给grep命令。这种思考方式是合理的,因为子进程会执行命令,并可能一直运行到完成。

strings_out = subprocess.Popen(('strings', file), stdout=subprocess.PIPE) 
strings_out.wait()
grep_output = subprocess.check_output(('grep', "Version = " + version_string), stdin=strings_out.stdout)

这段代码卡在了'strings_out.wait()'。我仍然不确定原因是什么。 - BaruchLi

0

很不错,我以前从没想到过可以像这样使用子进程的 stdin/stdout。不过,我的建议是要么纯粹使用 Python 编写一个在文件中查找字符串的方法,要么用更高级的 subprocess 方法。

Python 代码可能看起来像:

import os
search_term = bytes("Version = " + version_string, encoding='utf-8')
i = 0
found = False
file_size = os.stat(f).st_size
chunk_size = len(search_term) *10
with open(file_name, 'rb') as f:
    while f.tell() < size:
        x = f.read() #read a small amount of data
        i += chunk_size - len(search_term) #to make sure we don't miss the search_term
        f.seek(i)
        if search_term in x:
            found = True
            break

关于子进程:

cmd = f'strings {file_name} | grep "Version = {version_string}"'
test = subprocess.run([cmd], shell=True, capture_output=True)
test.returncode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接