执行 df | grep -w "/" 没有正确解析输出

Execute df | grep -w "/" not parsing output correctly

我正在尝试 运行 shell 命令 df -h | grep -w "/" 使用 python 来观察根分区的使用情况,并希望避免使用 shell=True 安全选项.

我试过的代码如下:

import subprocess
p1 = subprocess.Popen(['df', '-h'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', '-w', '"/"'], stdin=p1.stdout, stdout=subprocess.PIPE)
output=p2.communicate()[0]
print(output)

我得到的输出是:

$ ./subprocess_df_check.py 
b''

预期输出为:

$ df -h | grep -w "/"
/dev/sdd        251G  4.9G  234G   3% /

不要将子进程与 df 和/或 grep 一起使用。如果您已经使用 python,您可以使用 statvfs 函数调用,如:

import os
import time

path = "/"

while True:
    info = os.statvfs(path)
    print("Block size [%d]  Free blocks [%d]  Free inodes [%d]"
          % (info.f_bsize, info.f_bfree, info.f_ffree))
    time.sleep(15)

眼前的问题是添加了不必要的引号。

p2 = subprocess.Popen(['grep', '-w', '"/"'], stdin=p1.stdout, stdout=subprocess.PIPE)

等同于shell命令grep -w "/"。相反,它等效于 shell 命令 grep -w '"/"',(或 grep -w \"/\",或任何其他编写参数向量的方法,该向量在最后一个非 NUL 元素上传递文字双引号字符grep 的参数向量)和错误的原因相同。

使用 '/',而不是 '"/"'

好的,我想通了。

import subprocess
p1 = subprocess.Popen(['df', '-h'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', '-w', '/'], stdin=p1.stdout, stdout=subprocess.PIPE)
output=p2.communicate()[0].split()[4]
print("Root partition is of", output.decode(), "usage now")
  • 删除了不必要的双引号,从 subprocess.Popen(['grep', '-w', '"/"'] 更改为 subprocess.Popen(['grep', '-w', '/']。双引号用于 shell,不适用于 df。当你没有 shell 时,你不需要 shell 语法。
  • output=p2.communicate()[0].split()[4] 上,[0] 仅选择 stdout,而不是 stderr,如果没有错误则为 None。然后 split()[4] 从 shell df 命令中删除第 4 列磁盘使用百分比值。
  • output.decode()decode()是对编码后的字节字符串格式进行解码,避免输出结果前面的字符b。参考 here

所以脚本的输出是:

$ ./subprocess_df_check.py
Root partition is of 3% usage now

运行 grep 在单独的子进程中当然是不必要的。如果您正在使用 Python,您已经拥有了一个用于在字符串中查找子字符串的出色工具。

df = subprocess.run(['df', '-h'],
    capture_output=True, text=True, check=True)
for line in df.stdout.split('\n')[1:]:
    if '/' in line:
        print(line)

还请注意,如果可能,您基本上总是希望 subprocess.run 而不是 Popen,以及您希望 text=True 获取文本而不是 bytes。通常您还希望 check=True 确保子流程成功完成。