如何使用subprocess.check_output搜索行?

时间:2017-09-21 15:30:54

标签: python python-3.x

我有一个套接字连接,客户端提交他们的Windows用户名。然后,服务器运行“net user username / domain”以查找其到期日期。 我试图找到字符串“密码过期”并打印该行。

print(line)

什么都不给我。 如果我使用

print(result)

我确实获得了该命令的整个结果,但它有点乱码。 如何获得“密码过期”的行?我是否需要以某种方式对其进行格式化,以便“结果”看起来不会搞砸?

    import subprocess

    import os
    from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM
    import sys

    PORT_NUMBER = 3555
    SIZE = 1024

    hostName = gethostbyname( '0.0.0.0' )

    mySocket = socket( AF_INET, SOCK_DGRAM )
    mySocket.bind( (hostName, PORT_NUMBER) )

    print ("Test server listening on port {0}\n".format(PORT_NUMBER))

    # Receive no more than 1024 bytes


    while True:
        (data,addr) = mySocket.recvfrom(SIZE)
        try:
            #print >>sys.stderr, 'Received data from', addr
            while True:
                print (data.decode())
                batcmd=('net user ' + data.decode() + ' /domain')
                result = subprocess.check_output(batcmd, shell=True)
                # print (result)  shows details but it is messy looking
                for line in result:
                    if str(line).startswith("Password expires"):
                        print (line)

    #                      if data:
    #                          print >>sys.stderr, 'sending data back to the client'
    #                          mySocket.sendto({ },addr).format(line)
    #                          # TypeError: sendto() argument 1 must be string or buffer, not dict
    #                      else:
    #                          print >>sys.stderr, 'no more data from', client_address
    #                          break

                break

            # send result back to client ?
            #mySocket.send(result.encode('ascii'))
            sys.exit()
        finally:
            print('closing socket')
            mySocket.close()

如果我打印(结果),一切都如下所示:

.local.\r\n\r\nUser Name           js83838\r\nFull Name
    John Doe       \r\n\Country Code       Comment Here.
        Account active      Locked\r\nAccount expires
            more data like this
                and this

更新

我正在尝试这个并且它显示每一行而不是1.每行在它前面都有一个b'并且看起来正确对齐。

while True:
    (data,addr) = mySocket.recvfrom(SIZE)

    #print >>sys.stderr, 'Received data from', addr
    while True:
        print (data.decode())
        batcmd=('net user ' + data.decode() + ' /domain')
        result = subprocess.check_output(batcmd, shell=True)
        # print (result)  # shows details but it is messy looking
        for line in result.splitlines():
            if str(line).find("Password expires"):
                print (line)

2 个答案:

答案 0 :(得分:1)

subprocess.check_output不返回行,而是返回字节缓冲区。

将其解码为字符串后(Python 3中需要):

result = result.decode("ascii",errors="ignore")

你需要根据行进行拆分,否则你的循环将按char生成char,而startswith不会崩溃但却什么也找不到。

for line in result.splitlines():

诀窍。因此有两个问题:使用startswith检查整个缓冲区,而不是解码为str,这使搜索一无所获。

或者,不要decode,而是if line.startswith(b"Password expires"):。这使得代码与Python 2兼容是一种奖励。

除此之外:在解析net user的输出时要小心,因为字符串本地化可能会使您的程序错过信息。

答案 1 :(得分:0)

这是一个解决方案,允许您:逐行获取输出,只获取“密码过期”的行,而不是使用shell = True。

batcmd=['net', 'user', data.decode(), '/domain')
net_process = subprocess.Popen(batcmd, stdout=subprocess.PIPE)
grep_process= subprocess.Popen(["findstr", "Password expires"], stdin=net_process.stdout, stdout=subprocess.PIPE)  # or grep depending on your system
for line in grep_process.stdout.readlines():
    # do what you want