【问题标题】:Use of subprocess with Linux pipe command使用 Linux 管道命令使用子进程
【发布时间】:2020-12-07 06:57:14
【问题描述】:

我想从 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 内存不足。

我使用子流程有什么问题?

【问题讨论】:

  • 没有错,只是没有找到任何匹配项。
  • 你到底想做什么?只需检查匹配是否存在? (这个其实不需要grep,直接用Python就可以很方便的查看strings的输出。)
  • 我希望您需要在上述代码的第一行之后提及strings_out.wait()grep 命令可能在第一个命令未完成的情况下运行,例如,如果strings 命令的输出很大。
  • @alaniwi,你说直接在Python中检查字符串的输出是什么意思?
  • @BaruchLi 您可以将strings 的输出读入python 并使用python 正则表达式(或者甚至只是in 进行简单的子字符串搜索)来测试您正在寻找的版本字符串是否存在.

标签: python subprocess


【解决方案1】:

这很好,我从来没有想过像以前那样使用子进程标准输入/标准输出。但是,我的建议是要么使用纯 Python 并编写一个方法来搜索文件中的字符串,要么让你的子进程行更有趣。

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

【讨论】:

    【解决方案2】:

    正如@samsonjm 所提到的,每个成功运行的 bash 命令都有exit code = 0。这意味着grep 命令失败。此外,没有关于 OutofMemory 错误的线索。

    我怀疑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()”中。我仍然不确定为什么。
    【解决方案3】:

    check_output 的非零退出状态意味着 bash 命令有问题 - 我认为您没有内存不足。

    在测试自己时,我发现如果我给 grep 一个文件中存在的字符串,我会得到正确的代码输出(我没有使用 Version,因为我不知道你有什么输入文件,但是否则事情就差不多了)。但是,如果我 grep 一个不存在的字符串,我会得到同样的错误。

    也许您正在一个文件上运行它,该字符串不输出任何"Version = " + version_string 实例。如果您处于循环中,则只需一个文件没有正确的字符串即可获取错误。

    另一方面,如果您计划使用子进程完成这一行:strings &lt;FILE NAME&gt; | grep "Version = &lt;VERSION STRING&gt;" &gt; /dev/null,您将通过管道将输出传送到 /dev/null。在这种情况下,您将看不到 grep 的输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-08
      • 1970-01-01
      • 1970-01-01
      • 2022-10-19
      • 1970-01-01
      • 1970-01-01
      • 2012-06-18
      • 2021-11-01
      相关资源
      最近更新 更多