执行 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
确保子流程成功完成。
我正在尝试 运行 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]
从 shelldf
命令中删除第 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
确保子流程成功完成。