简体   繁体   English

subprocess.Popen没有运行shell命令

[英]subprocess.Popen is not running shell command

I am trying to use subprocess.Popen to run 'cat test.txt | 我正在尝试使用subprocess.Popen运行'cat test.txt | grep txt' , but it's not working. grep txt' ,但无法正常工作。 In my code I have executed the subprocess.Popen command twice. 在我的代码中,我已经执行了subprocess.Popen命令两次。

1: First time I used it to run a tshark command which redirectes the command output to a text (test.txt) file (which works fine). 1:第一次使用它运行tshark命令,该命令将命令输出重定向到文本(test.txt)文件(工作正常)。 ( defined in function get_all_tshark_out in below code ) 在下面的代码中的get_all_tshark_out函数中定义

2: Second time used subprocess.Popen to run 'cat test.txt | 2:第二次使用subprocess.Popen运行'cat test.txt | grep txt' command to extract txt from this file to perform some validation. grep txt'命令从该文件中提取txt,以执行一些验证。 This didn't work for me. 这对我不起作用。 ( defined in function get_uniq_sessions in below code ) 在下面的代码中的get_uniq_sessions函数中定义

To make sure it's not because of buffer overflow I am flushing stdout also, but didn't get any help. 为了确保不是因为缓冲区溢出,我也在刷新stdout ,但是没有得到任何帮助。 Below is my code: 下面是我的代码:

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

How do I fix this? 我该如何解决?

TL;DR Both of your subprocess.Popen() calls are broken; TL; DR 两个 subprocess.Popen()调用均已损坏; use one of the wrapper methods in subprocess instead, and/or use Python's built-in facilities instead of external tools. 而是在subprocess使用包装方法之一,和/或使用Python的内置工具代替外部工具。

Is there a particular reason you use a useless use of cat ? 您是否有使用cat无用原因? Just subprocess.Popen(['grep', id, uniqlog_file]) would be much simpler, and not require shell=True -- but of course, Python by itself is excellent at reading files and checking whether each line contains a string. 只是subprocess.Popen(['grep', id, uniqlog_file])会简单得多,并且不需要shell=True subprocess.Popen(['grep', id, uniqlog_file])但是,当然,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

Your functions should probably not call sys.exit() ; 您的函数可能不应该调用sys.exit() instead, raise an exception, or just return None -- that way, the calling code can decide how to handle errors and exceptions. 而是引发一个异常,或者只返回None这样,调用代码可以决定如何处理错误和异常。

Your remaining subprocess.Popen() only coincidentally works as long as there is a limited amount of output. 只要输出量有限,剩下的subprocess.Popen()只能同时起作用。 You should probably use subprocess.call instead, which exists precisely for the purpose of running a subprocess under controlled conditions while checking for errors. 您可能应该改用subprocess.call ,它的存在正是为了在检查错误的同时在受控条件下运行子流程。

The key observation here is that Popen() itself merely spawns the subprocess. 此处的主要观察结果是Popen()本身仅产生了子进程。 You need to interact with it and wait() for it in order to make sure it succeeds and returns all its output. 您需要与它进行交互,并wait()wait()以确保它成功并返回所有输出。 The call and various check_* methods in the subprocess module do this for you; subprocess模块中call和各种check_*方法可以为您完成此操作; Popen() is useful mainly when you outgrow the facilities of those canned wrappers, but also somewhat more tricky to get right, especially the first time. Popen()主要在您不再使用那些罐装包装程序的功能时很有用,但在正确使用时也比较棘手,尤其是在第一次使用时。

The tshark command would not require a shell=True if you picked it apart into a list yourself, and did the sorting and writing to a file in Python. 如果您自己将tshark命令拆成一个列表,并使用Python进行排序和写入文件,则不需要shell=True If the sole purpose of the output file is to open it again from Python, I would recommend reading the raw output into a Python string and doing all the remaining processing in 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)

... and now your get_uniq_sessions function is basically a one-liner: ...现在,您的get_uniq_sessions函数基本上是一种形式:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM