Subprocess Python ..将命令串在一起

时间:2012-05-25 01:18:28

标签: python linux python-3.x subprocess

我正在编写一个Python程序,需要返回在我的一个漏洞扫描中扫描的活动主机。我在返回XML之前使用过这种方法,但是当我尝试使用cut和grep这些额外的程序时,我遇到了问题。也许它不喜欢“管道”|或者我可能在这里使用逗号做了一些完全错误但是我已经尝试了各种各样的东西,并且似乎无法让它返回结果,就像我从命令行独立运行命令一样。非常感谢您提供的任何帮助。

def activeHostsQuery():
    args = ['curl', '-s', '-k', '-H', 'X-Requested-With: curl demoapp', '-u','username:password', 'https://qualysapi.qualys.com/api/2.0/fo/scan/?action=fetch&scan_ref=scan/1111111.22222&mode=brief&output_format=csv', '|', 'cut', '-d', '-f1', '|', 'sort', '|', 'uniq', '|', 'grep', '-E', '"\"[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\""', '|', 'wc', '-l']

    activeHostsNumber = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
    return activeHostsNumber

3 个答案:

答案 0 :(得分:6)

将命令串在一起的正确方法 - 如果你想保留shell,你应该这样做 - 就是创建多个Popen对象。

def activeHostsQuery():
    args1 = ['curl', '-s', '-k',
             '-H', 'X-Requested-With: curl demoapp',
             '-u','username:password',
             'https://qualysapi.qualys.com/api/2.0/fo/scan/?action=fetch&scan_ref=scan/1111111.22222&mode=brief&output_format=csv']
    args2 = ['cut', '-d', '-f1']
    args3 = ['sort', '-u']
    args4 = ['grep', '-E', '"\"[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\""']
    args5 = ['wc', '-l']

    p1 = subprocess.Popen(args1, stdout=subprocess.PIPE)
    p2 = subprocess.Popen(args2, stdin=p1.stdout, stdout=subprocess.PIPE); p1.stdout.close()
    p3 = subprocess.Popen(args3, stdin=p2.stdout, stdout=subprocess.PIPE); p2.stdout.close()
    p4 = subprocess.Popen(args4, stdin=p3.stdout, stdout=subprocess.PIPE); p3.stdout.close()
    p5 = subprocess.Popen(args5, stdin=p4.stdout, stdout=subprocess.PIPE); p4.stdout.close()
    activeHostsNumber = p5.communicate()[0]
    return activeHostsNumber

这样做的好处是没有涉及shell - 您可以将任意变量替换到您的参数列表中,而不必担心它们会被字符串拆分,误解,导致重定向或其他任何内容,以及参数之间的区别用于生成您的列表将被尊重。

现在,在这个特定的情况下,我会在本机Python中完成所有工作 - 当你有本机HTTP库时,甚至没有理由使用curl - 但是知道如何构建管道使用subprocess.Popen在任何情况下都很有用。

答案 1 :(得分:0)

我会试试这个:

def activeHostsQuery():
    args = ['curl', '-s', '-k', '-H', 'X-Requested-With: curl demoapp', '-u','username:password', 'https://qualysapi.qualys.com/api/2.0/fo/scan/?action=fetch&scan_ref=scan/1111111.22222&mode=brief&output_format=csv', '|', 'cut', '-d', '-f1', '|', 'sort', '|', 'uniq', '|', 'grep', '-E', '"\"[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\""', '|', 'wc', '-l']

    activeHostsNumber = subprocess.Popen(" ".join("'%s'" % a for a in args), shell=True, stdout=subprocess.PIPE).communicate()[0]
    return activeHostsNumber

修改:在参数周围添加引号。

另一个编辑:好的,尝试将命令设为一个字符串:

def activeHostsQuery():
    cmd = 'curl -s -k -H \'X-Requested-With: curl demoapp\' -u username:password \'https://qualysapi.qualys.com/api/2.0/fo/scan/?action=fetch&scan_ref=scan/1111111.22222&mode=brief&output_format=csv\' | cut -d, -f1 | sort | uniq | grep -E \'"[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}"\' | wc -l'

    ctiveHostsNumber = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE).communicate()[0]
    return activeHostsNumber

答案 2 :(得分:0)

我知道这不回答问题......但那是shell脚本。 如果您希望shell脚本将参数传递给sh -c(或bash或其他)

    args = ['sh', '-c', 'curl -s -k -H X-Requested-With: curl demoapp -u','username:password https://qualysapi.qualys.com/api/2.0/fo/scan/?action=fetch&scan_ref=scan/1111111.22222&mode=brief&output_format=csv | cut -d -f1 | sort | uniq | grep -E "\"[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\"" | wc -l'


   count = int(cubprcess.check_output(args))

或像其他人建议的那样使用shell=True。如果你关心这些事情,这肯定不适用于Windows。

你应该做的事情应该是:

import requests
from csv
from StringIO import StringIO
import re

req=reqeusts.get(
    'https://qualysapi.qualys.com/api/2.0/fo/scan/?action=fetch&scan_ref=scan/1111111.22222&mode=brief&output_format=csv',
    auth=('username','passoword'),
    headers={'X-Requested-With': 'curl demoapp'})

reader = csv.reader(StringIO(req.text))
count = 0
for line in reader:
    if re.match(r'.*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.*',line[0]) is not None:
        count += 1

print count