subprocess.Popen没有运行shell命令

时间:2015-12-08 10:49:22

标签: python python-2.7 subprocess popen

我正在尝试使用subprocess.Popen来运行' cat test.txt | grep txt' ,但它不起作用。在我的代码中,我执行了两次subprocess.Popen命令。

  

1:我第一次使用它运行tshark命令,将命令输出重定向到文本(test.txt)文件(工作正常)。 (在以下代码中的函数get_all_tshark_out中定义

     

2:第二次使用subprocess.Popen运行' cat test.txt | grep txt'命令从此文件中提取txt以执行某些验证。这对我没有用。 (在以下代码中的函数get_uniq_sessions中定义

为了确保它不是因为缓冲区溢出而我正在刷新stdout,但没有得到任何帮助。以下是我的代码:

import subprocess
import logging

def get_all_tshark_out(logger, tcpdump, port):
    command = """tshark -r "%s" -odiameter.tcp.ports:"%s" -R 'diameter.cmd.code == 272 and diameter.flags.request==0 and !tcp.analysis.retransmission and diameter.flags.T == 0' -Tpdml -Tfields -ediameter.Session-Id | sort > test.txt""" %(tcpdump, port)
    p_out = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    sys.stdout.flush()
    sys.stderr.flush()
    return 1

def get_uniq_sessions(logger, id='1234', uniqlog_file='test.txt'):
    command = "cat "+ uniqlog_file +" | grep "+ id
    print command
    p_out = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    print "PPPPP", p_out
    output = p_out.stdout.read()
    p_out.wait()
    command_out_list = (output.strip().split("\n"))
    sys.stdout.flush()
    print "%%%", output, p_out.stderr.read()
    print len(command_out_list)
    if p_out.stderr.read():
        logger.error("\"%s\" Error happened while trying to execute \"%s\"" (p_out.stderr.read().strip(), command))
        sys.exit(1)
    elif command_out_list[0] == '' and len(command_out_list) == 1:
        logger.error("No Sessions belongs to %s campaign ID please provide proper input as Campaign ID" %id)
        sys.exit(1)
    else:
        return command_out_list

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

TL; DR 您的subprocess.Popen()来电的两个都已损坏;改为使用subprocess中的一个包装器方法,和/或使用Python的内置工具而不是外部工具。

您使用useless use of cat是否有特殊原因?只需subprocess.Popen(['grep', id, uniqlog_file])就会简单得多,而且不需要shell=True - 但当然,Python本身非常适合读取文件并检查每行是否包含字符串。

def get_uniq_sessions(logger, id='1234', uniqlog_file='test.txt'):
    matches = []
    with open(uniqlog_file, 'r') as handle:
        for line in handle:
            if id in line:
                matches.append(line)
    return matches

你的功能可能不应该叫sys.exit();相反,引发异常,或只返回None - 这样,调用代码可以决定如何处理错误和异常。

只要输出数量有限,您剩余的subprocess.Popen()才会巧合。您可能应该使用subprocess.call,这恰好是为了在检查错误时在受控条件下运行子进程而存在。

这里的关键观察是Popen()本身只是产生子进程。您需要与它进行交互并wait()为它进行交互,以确保它成功并返回其所有输出。 subprocess module中的call和各种check_*方法为您执行此操作; Popen()主要适用于那些罐装包装纸的设施,但也更难以正确使用,尤其是第一次。

tshark命令不需要shell=True如果您自己将其分成列表,并在Python中进行排序和写入文件。如果输出文件的唯一目的是从Python再次打开它,我建议将原始输出读入Python字符串并在Python中执行所有剩余的处理。

def get_all_tshark_out(logger, tcpdump, port):
    output = subprocess.check_output(['tshark', '-r', str(tcpdump),
        '-odiameter.tcp.ports:{0}'.format(port), '-R',
        'diameter.cmd.code == 272 and diameter.flags.request==0 '
            'and !tcp.analysis.retransmission and diameter.flags.T == 0',
        '-Tpdml', '-Tfields', '-ediameter.Session-Id'])
    return sorted(output)

...现在你的get_uniq_sessions功能基本上是一个单行:

 session = [x for x in get_all_tshark_out() if '1234' in x]