简体   繁体   English

子流程的输出操作

[英]Output manipulation from subprocess

I'd like to manipulate the output from a subprocess call and only print specific details. 我想操纵子流程调用的输出,并且只打印特定的细节。 Now I was originally going down the PIPE route and piping the output to another subprocess of grep but this seemed too limiting, meaning I could only print a few lines (some of which I didn't want), by using the -A or -B grep arguments. 现在,我原本是沿着PIPE路线走,然后将输出传递给grep另一个subprocess ,但这似乎太局限了,这意味着我只能使用-A-B打印几行(其中一些是我不想要的) -B grep参数。 So now I'm taking the stdout.readline route. 所以现在我要走stdout.readline路线。 My question is, is there a better way to do achieve what I am trying to do? 我的问题是,是否有更好的方法来实现我想要做的事情? Is pattern matching with regular expressions and re the best option? 被图案用正则表达式匹配和re最好的选择?

Below is the code for both trails of thought, just to give some context. 下面是两种思路的代码,仅用于提供一些上下文。

PIPE to another subprocess: PIPE到另一个子流程:

def nmap_ips(ip_list):

    for ip in ip_list:
        cmd1 = subprocess.Popen(["nmap", "-sC", "--open", "-Pn", "-p80,443", ip], stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
        cmd2 = subprocess.Popen(["grep", "title", "-A", "1"], stdin=cmd1.stdout)
        cmd1.stdout.close()
        output = cmd2.communicate()[0]

stdout read lines: #Im not actually getting output from this function at the moment, I'm guessing it's my regex stdout读取以下行: #我目前实际上尚未从此函数获取输出,我猜这是我的正则表达式

def nmap_ips(ip_list):
   regs = ["title", "commonName"]
   combined = "|".join(regs)

   for ip in ip_list:
      p = subprocess.Popen(["nmap", "-sC", "--open", "-Pn", "-p80,443", ip], stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
      for line in iter(p.stdout.readline, b''):
         ml = re.match(combined, line)
         if ml:
            print ml.group()

Example of data I am trying to manipulate 我试图处理的数据示例

Starting Nmap 6.40 ( http://nmap.org ) at 2014-10-10 23:47 BST
Nmap scan report for BTHomeHub.home (192.168.1.254)
Host is up (0.0054s latency).
PORT    STATE SERVICE
80/tcp  open  http
| http-title: Home Hub Manager - Please Reset Your Password
|_Requested resource was http://BTHomeHub.home/html/home/a_firstlogin_configuration.html
443/tcp open  https
| ssl-cert: Subject: commonName=bthomehub.home/countryName=UK
| Not valid before: 2011-01-15T16:52:23+00:00
|_Not valid after:  2024-01-17T16:52:23+00:00
|_ssl-date: 2014-10-10T22:47:18+00:00; +14s from local time.

Your approach is fine. 您的方法很好。 Both grep 'title\\|commonName' and re.search(b'title|commonName', line) should work. re.search(b'title|commonName', line) grep 'title\\|commonName're.search(b'title|commonName', line)都应该起作用。

Note: re.match() starts matching at the begining of its input string. 注意: re.match()在其输入字符串的开头开始匹配。 re.search() finds the match anywhere in the string. re.search()在字符串中的任意位置查找匹配项。

If you want to save these lines in a variable then the grep process is unnecessary. 如果要将这些行保存在变量中,则不需要grep进程。 It is enough to start only nmap . 仅启动nmap就足够了。

from subprocess import Popen, PIPE, STDOUT

def nmap_something(ip_list):
    match = re.compile(b"title|commonName").search
    p = Popen(["nmap", "-sC", "--open", "-Pn", "-p80,443"] + ip_list,
              stdout=PIPE, stderr=STDOUT, bufsize=1)
    result = list(filter(match, p.stdout))
    p.stdout.close()
    p.wait()
    return result

I'm not sure about the exact syntax to pass multiple ips to a single nmap child process but it supports it ie, you don't need to start multiple processes to scan multiple ips. 我不确定将多个ip传递给单个nmap子进程的确切语法,但是它支持它,即,您不需要启动多个进程来扫描多个ip。

If you want to print ssl certificates for web servers then you don't need nmap , you could use a pure Python solution eg, see How to get server's ssl certificate in a human readable form? 如果要为Web服务器打印ssl证书,则不需要nmap ,可以使用纯Python解决方案,例如,请参阅如何以人类可读的形式获取服务器的ssl证书?

After some advice from JFSebastian, I changed to re.search and found printing the line directly achieved what I was after. 在得到JFSebastian的建议后,我转而使用re.search ,发现直接打印该行可以达到我的预期。

def nmap_ips(ip_list):
    regs = ["title", "commonName"]
    combined = "|".join(regs)

    for ip in ip_list:
        p = subprocess.Popen(["nmap", "-sC", "--open", "-Pn", "-p80,443", ip], stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
        for line in iter(p.stdout.readline, b''):
            ml = re.search(combined, line)
            if ml:
                print line

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

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