【问题标题】:python shell command pipes grep no resultspython shell命令管道grep没有结果
【发布时间】:2018-12-10 01:04:47
【问题描述】:

我正在尝试从 python 中的 cpanel 用户获取域名。

这是我的代码:

import subprocess
user = "testuser"
getuserdata = 'cat /var/cpanel/users/' + user
getdnsline = 'grep "DNS="'
test = 'wc -l'

userdataprocess = subprocess.Popen(getuserdata.split(), stdout=subprocess.PIPE)

testprocess = subprocess.Popen(test.split(), stdin=userdataprocess.stdout, stdout=subprocess.PIPE)

test, error = testprocess.communicate()
print(test)

dnslineprocess = subprocess.Popen(getdnsline.split(), stdin=userdataprocess.stdout, stdout=subprocess.PIPE)

website, error = dnslineprocess.communicate()
print(website.decode('utf-8').splitlines())

我的输出是:

b'60\n'
[]

这意味着 wc -l 命令返回 60 行。因此,将第一个 getuserdata 命令的输出传递给 wc -l 命令是可行的。

但是,grep 命令总是返回空白。无论我输入“DNS =”还是“=”甚至是“a”。该文件是普通的cpanel用户文件,我已经验证了DNS在文件中。

当我从第一个进程 userdataprocess 输出数据时,我可以手动检查 DNS 条目。

以这种方式使用 grep 命令时,我是否需要做一些不同的事情?

【问题讨论】:

  • userdataprocess.stdoutdnslineprocess 运行时为空,因为testprocess 已经消耗了所有这些。我不知道有一个简单的解决方法 - 但无论如何你对subprocess 的使用是完全没有必要的:你用它做的一切(读取文件、计算行数、检查这些行中的特定文本)都是微不足道的直接在 Python 中。

标签: python subprocess pipe


【解决方案1】:

您的脚本因DNS= 周围的引号而失败。

您可以使用shell=True 使脚本工作:

dnslineprocess = subprocess.Popen(getdnsline, stdin=userdataprocess.stdout, stdout=subprocess.PIPE, shell=True)

来源:Passing double quote shell commands in python to subprocess.Popen()?

【讨论】:

    【解决方案2】:

    这是因为wc -l 命令的testprocess.communicate() 已经消耗了userdataprocess.stdout 的所有输出并实际上将其关闭,因此dnslineprocess.communicate() 没有任何内容可供阅读。

    您应该将userdataprocess.stdout 的输出读入一个变量,然后将其用作testprocess.communicate()dnslineprocess.communicate() 的输入。

    此外,正如@pyb 指出的那样,您在grep 命令中不必要地引用DNS=,如果没有shell,它将被传递给grep,其中包含双引号作为过滤字符串的一部分.您应该简单地删除它们,因为您的过滤器字符串中没有特殊字符。

    import subprocess
    user = "testuser"
    getuserdata = 'cat /var/cpanel/users/' + user
    getdnsline = 'grep DNS='
    test = 'wc -l'
    
    userdataprocess = subprocess.Popen(getuserdata.split(), stdout=subprocess.PIPE)
    
    userdata = userdataprocess.stdout.read()
    
    testprocess = subprocess.Popen(test.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    
    test, error = testprocess.communicate(userdata)
    print(test)
    
    dnslineprocess = subprocess.Popen(getdnsline.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    
    website, error = dnslineprocess.communicate(userdata)
    print(website.decode('utf-8').splitlines())
    

    【讨论】:

    • 那行不通。我也想到了,评论了调用wc -l的部分,得到了同样的结果。
    • 它确实有效,但第二个问题是 pyb 指出的,OP 不必要地引用了DNS=。我已经相应地编辑了答案。