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

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

环境描述:

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

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

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

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

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

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

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

# this method is used for monitoring

import time
import subprocess
import locale
import codecs mylist = []
ps = subprocess.Popen('netstat -a', stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
while True:
data = ps.stdout.readline()
if data == b'':
if ps.poll() is not None:
break
else:
mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))
newlist = []
for i in mylist:
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

import time
import subprocess
import locale
import codecs def getstdout(p):
mylist = []
while True:
data = p.stdout.readline()
if data == b'':
if p.poll() is not None:
break
else:
mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))
return mylist while True:
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

import time
import subprocess
import locale
import codecs def getstdout(p):
mylist = []
while True:
data = p.stdout.readline()
if data == b'':
if p.poll() is not None:
break
else:
mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))
return mylist while True:
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 in alist:
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()的问题。忽然想起来多线程这个利器,干脆开一个线程,不返回就等着,不就问题解决了。

# this method is used for monitoring

import time
import subprocess
import locale
import codecs
import threading alist = [] def getstdout(p, asy):
if asy:
alist.clear()
mylist = []
while True:
data = p.stdout.readline()
if data == b'':
if p.poll() is not None:
break
else:
if asy:
alist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))
else:
mylist.append(data.decode(codecs.lookup(locale.getpreferredencoding()).name))
return mylist while True:
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 in alist:
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)

总结

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

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

使用Python实时获取cmd的输出的更多相关文章

  1. 这个帖子要收藏,以后用得着--python 实时获取子进程输出

    在论坛上找到方法了,http://bbs.csdn.net/topics/340234292 http://blog.csdn.net/junshao90/article/details/821575 ...

  2. Python实时获取贴吧邮箱名单并向其发送邮件

    本人Python大菜鸟,今天用python写了一个脚本.主要功能是获取贴吧指定贴子评论中留下的邮箱,通过系统的crontab每一分钟自动检测新邮箱并向其发送邮件,检测机制是去查询数据库的记录,也就是不 ...

  3. 用Python实时获取Steam特惠游戏数据,我看看谁的钱包还有钱

    前言 大家好鸭, 我是小熊猫 Steam大家应该不陌生吧?不知道的话就让我们来了解一下吧~(一下简称"S") S是由美国电子游戏商Valve于2003年9月12日推出的数字发行平台 ...

  4. Python之uiautomation模块-获取CMD窗口中所打印的文字信息

    当我们想以自动化的方式操作软件,以提高办公或测试效率时,有许多成熟的工具,比如针对Web端应用的Selenium.针对移动端应用的Appium.那么,PC端(Windows)桌面应用,又改如何处理呢? ...

  5. 【转】Python中执行cmd的三种方式

    原文链接:http://blog.csdn.net/menglei8625/article/details/7494094 目前我使用到的python中执行cmd的方式有三种: 1. 使用os.sys ...

  6. Python实时语音识别控制

    代码地址如下:http://www.demodashi.com/demo/12946.html Python实时语音识别控制 概述 本文中的语音识别功能采用 百度语音识别库 ,首先利用 PyAudio ...

  7. subprocess.Popen stdout重定向内容实时获取

    python 打开一个新进程执行系统命令, test 执行完才能获取返回, test1 实时获取返回结果 import subprocess def test(cmd): p = subprocess ...

  8. Python中获取异常(Exception)信息

    异常信息的获取对于程序的调试非常重要,可以有助于快速定位有错误程序语句的位置.下面介绍几种python中获取异常信息的方法,这里获取异常(Exception)信息采用try...except...程序 ...

  9. python基础——获取对象信息

    python基础——获取对象信息 当我们拿到一个对象的引用时,如何知道这个对象是什么类型.有哪些方法呢? 使用type() 首先,我们来判断对象类型,使用type()函数: 基本类型都可以用type( ...

随机推荐

  1. 在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法

    在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法 在Eclipse中运行Jboss时,时间太长可能有时候会出现java ...

  2. Ctrl+Alt+F1~F6

    Ctrl+ALT+F1~F6 可以进入不同的字符终端和图形界面.体现了 linux 或者 unix 的多用户的特点. 6个不同的终端,相当于六个不同的用户. 保持更新,转载请著名出处.

  3. Python3编写网络爬虫01-基本请求库urllib的使用

    安装python后 自带urllib库 模块篇 分为几个模块如下: 1. urllib.request 请求模块 2. urllib.parse 分析模块 3. urllib.error 异常处理模块 ...

  4. docker-compose.md

    安装 pip python 2.7+的系统同yum先安装pip命令. # yum install -y python2-pip # pip install docker-compose 网络安装 # ...

  5. js面对对象编程(二):属性和闭包

    上篇博客中解说了一些js对象的基本概念和使用方法.这篇博客解说一下js属性方面的:公有属性.私有属性,特权方法. 假设学过java.公有属性.私有属性,特权方法(即能够訪问和设置私有属性的方法)一定非 ...

  6. 死磕nginx系列--使用upsync模块实现负载均衡

    问题描述 nginx reload是有一定损耗的,如果你使用的是长连接的话,那么当reload nginx时长连接所有的worker进程会进行优雅退出,并当该worker进程上的所有连接都释放时,进程 ...

  7. 2298: [HAOI2011]problem a

    Description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) 这句话的意思就等于是说第i个 ...

  8. BeiDou开源项目

    本文主要围绕着BeiDou是什么及其安装和快速开始等两个方面,希望能够对初学者和对此感兴趣的朋友有所帮助. 一. BeiDou是什么 它是服务器呈现的React应用程序的同构框架 特征如下: ✔︎高性 ...

  9. jq中each的中断

    最近在做项目中,遇到jq的each方法中的回调函数里面的break不生效,即通过 jquery 的循环方法进行数组遍历,但是当不符合条件时,怎么跳出当前循环,我们经常会习惯JS中的break和cont ...

  10. ROS初级教程 cmake cmakelist.txt 的编写教程

    有很多 的时候我们使用别人的程序包.然后添加东西的时候缺少什么东西,会使程序编译不过去,甚至无法运行,接下来介绍一下cmakelist.txt 的每一行的作用.为了以后添加和修改方便. 2.整体结构和 ...