python 获取屏幕输出_使用Python实时获取cmd的输出

最近发现一个问题,一个小伙儿写的console程序不够健壮,监听SOCKET的时候容易崩,造成程序的整体奔溃,无奈他没有找到问题的解决办法,一直解决不了,可是这又是一个监控程序,还是比较要紧的,又必须想办法解决。

(这是要搞死我的节奏啊....)由于个人不太懂他用的语言,只能在程序外围想办法。

环境描述:

1. 目标程序执行时会监听8080端口,TCP,并在每一次client连接后通过console输出client的IP地址。

2. 监听不是一次性完成的,而是一直监听,程序并不会退出

3. 为了监控需要,最好能对连接的IP进行排序,整理。

P.S. 系统基于windows平台。

想起来做监控程序,简单点比较好,于是想到了Python。

我的预想逻辑是这样的,通过python检测目标程序是否崩了,如果中标就启动目标程序,并进行监控,每输出一次,python进行一次数据运算整理,然后循环。

第一步,先搞定输出的捕获问题。

#this method is used for monitoring

importtimeimportsubprocessimportlocaleimportcodecs

mylist=[]

ps= subprocess.Popen('netstat -a', stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)whileTrue:

data=ps.stdout.readline()if data == b'':if ps.poll() is notNone:break

else:

mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))

newlist=[]for i inmylist:if i.find('192.168') >0:

newlist.append(i)

newlist.sort()print('Sum of requests from LAN:', len(newlist))

我用netstat -a替代那个需要持续输出的程序,执行程序,发现程序和想象的不太一样,确实是实时获得数据了,但是感觉总是有点不太和谐,不管了,继续。

第二步,解决监控程序的问题

程序或者还是死的,有一点非常关键,就是监听端口,那只要检测一下端口就行了。三个办法:

1. 找端口检测的API

2. 连接一次目标端口,通了就是活的

3. netstat

第一种方法需要去找找有没有相关的API,第二种方法容易对目标程序的正常运行造成问题,第三种我想都没想就用了吧。这里需要用到cmd的重定向功能

#this method is used for monitoring

importtimeimportsubprocessimportlocaleimportcodecsdefgetstdout(p):

mylist=[]whileTrue:

data=p.stdout.readline()if data == b'':if p.poll() is notNone:break

else:

mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))returnmylistwhileTrue:

ps= subprocess.Popen('netstat -an | findstr "8080"', stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

resultlist=getstdout(ps)if len(resultlist) >= 1:pass

else:print(time.strftime("%Y-%m-%d %H:%M:%S"))

subprocess.Popen('taskkill.exe /f /im node.exe', shell=False)

# 防止动作过快,把新建的程序整死了

time.sleep(3)

subprocess.Popen('start node D:\\app.js', shell=True)

time.sleep(10)

netstat -an获得当前的端口监听情况,“|”将netstat的输出重定向到findstr函数

netstat -an | findstr "8080" 查找有8080端口的地址行,有就说明活着,否则就是挂了。

最后一步,整合

#this method is used for monitoring

importtimeimportsubprocessimportlocaleimportcodecsdefgetstdout(p):

mylist=[]whileTrue:

data=p.stdout.readline()if data == b'':if p.poll() is notNone:break

else:

mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))returnmylistwhileTrue:

ps= subprocess.Popen('netstat -an | findstr "8080"', stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

resultlist=getstdout(ps)if len(resultlist) >= 1:pass

else:print(time.strftime("%Y-%m-%d %H:%M:%S"))

subprocess.Popen('taskkill.exe /f /im node.exe', shell=False)

time.sleep(3)

pss= subprocess.Popen('start cmd.exe /k node app.js', stdin=subprocess.PIPE,

stdout=subprocess.PIPE, shell=True)

alist=getstdout(pss)

newlist=[]for i inalist:if i.find('192.168') >0:

newlist.append(i)

newlist.sort()print('Sum of requests from LAN:', len(newlist))

time.sleep(10)

然后发现有问题,程序完全不会定时检测,只会卡在readline()上。

各种找问题,发现那个process.stdout.readline()是个同步方法,没结果就不返回。有没有的能异步的方法?

有人用fnctl,windows不支持,pass

asyncio?看了半天没太明白...

折腾了半天,最后关头我还是用c#解决这个问题了....

参考代码见http://www.jiamaocode.com/Cts/1031.html,打不开的话http://www.cnblogs.com/sode/archive/2012/07/10/2583941.html有转载

总算解决了这个问题,但是我心中还是不爽,思考了很久如何解决异步readline()的问题。忽然想起来多线程这个利器,干脆开一个线程,不返回就等着,不就问题解决了。

ContractedBlock.gif

ExpandedBlockStart.gif

#this method is used for monitoring

importtimeimportsubprocessimportlocaleimportcodecsimportthreading

alist=[]defgetstdout(p, asy):ifasy:

alist.clear()

mylist=[]whileTrue:

data=p.stdout.readline()if data == b'':if p.poll() is notNone:break

else:ifasy:

alist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))else:

mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))returnmylistwhileTrue:

ps= subprocess.Popen('netstat -an | findstr "8080"', stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

resultlist=getstdout(ps, False)if len(resultlist) >= 1:

newlist=[]for i inalist:if i.find('192.168') >0:

newlist.append(i)

newlist.sort()print('Sum of requests from LAN:', len(newlist))else:print(time.strftime("%Y-%m-%d %H:%M:%S"))

subprocess.Popen('taskkill.exe /f /im node.exe', shell=False)

time.sleep(3)

pss= subprocess.Popen('start cmd.exe /k node app.js', stdin=subprocess.PIPE,

stdout=subprocess.PIPE, shell=True)

th= threading.Thread(target=getstdout, args=[pss, True])

th.start()

time.sleep(10)

View Code

总结

有时候简单的解决方法也可以实现同样的功能,对比python的实现与C#的实现,C#更面向事件一点,python应该也有不错的解决方案,继续摸索...

P.S. 注意cmd输出在UNICODE系统是b''这种类型的字符串,转码对自己系统的默认编码不清楚的建议用codecs.lookup(locale.getpreferredencoding()).name,贸然用utf-8各种坑。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值