Python實(shí)時(shí)獲取cmd的輸出
最近發(fā)現(xiàn)一個問題,一個小伙兒寫的console程序不夠健壯,監(jiān)聽SOCKET的時(shí)候容易崩,造成程序的整體奔潰,無奈他沒有找到問題的解決辦法,一直解決不了,可是這又是一個監(jiān)控程序,還是比較要緊的,又必須想辦法解決。
(這是要搞死我的節(jié)奏啊....)由于個人不太懂他用的語言,只能在程序外圍想辦法。
環(huán)境描述:
1. 目標(biāo)程序執(zhí)行時(shí)會監(jiān)聽8080端口,TCP,并在每一次client連接后通過console輸出client的IP地址。
2. 監(jiān)聽不是一次性完成的,而是一直監(jiān)聽,程序并不會退出
3. 為了監(jiān)控需要,最好能對連接的IP進(jìn)行排序,整理。
P.S. 系統(tǒng)基于windows平臺。
想起來做監(jiān)控程序,簡單點(diǎn)比較好,于是想到了Python。
我的預(yù)想邏輯是這樣的,通過python檢測目標(biāo)程序是否崩了,如果中標(biāo)就啟動目標(biāo)程序,并進(jìn)行監(jiān)控,每輸出一次,python進(jìn)行一次數(shù)據(jù)運(yùn)算整理,然后循環(huán)。
第一步,先搞定輸出的捕獲問題。
# 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替代那個需要持續(xù)輸出的程序,執(zhí)行程序,發(fā)現(xiàn)程序和想象的不太一樣,確實(shí)是實(shí)時(shí)獲得數(shù)據(jù)了,但是感覺總是有點(diǎn)不太和諧,不管了,繼續(xù)。
第二步,解決監(jiān)控程序的問題
程序或者還是死的,有一點(diǎn)非常關(guān)鍵,就是監(jiān)聽端口,那只要檢測一下端口就行了。三個辦法:
1. 找端口檢測的API
2. 連接一次目標(biāo)端口,通了就是活的
3. netstat
第一種方法需要去找找有沒有相關(guān)的API,第二種方法容易對目標(biāo)程序的正常運(yùn)行造成問題,第三種我想都沒想就用了吧。這里需要用到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獲得當(dāng)前的端口監(jiān)聽情況,“|”將netstat的輸出重定向到findstr函數(shù)
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)
然后發(fā)現(xiàn)有問題,程序完全不會定時(shí)檢測,只會卡在readline()上。
各種找問題,發(fā)現(xiàn)那個process.stdout.readline()是個同步方法,沒結(jié)果就不返回。有沒有的能異步的方法?
有人用fnctl,windows不支持,pass
asyncio?看了半天沒太明白...
折騰了半天,最后關(guān)頭我還是用c#解決這個問題了....
參考代碼見http://www.jiamaocode.com/Cts/1031.html,打不開的話http://www.cnblogs.com/sode/archive/2012/07/10/2583941.html有轉(zhuǎn)載
總算解決了這個問題,但是我心中還是不爽,思考了很久如何解決異步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 ""', stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
resultlist = getstdout(ps, False)
if len(resultlist) >= :
newlist = []
for i in alist:
if i.find('.') > :
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()
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()
總結(jié)
有時(shí)候簡單的解決方法也可以實(shí)現(xiàn)同樣的功能,對比python的實(shí)現(xiàn)與C#的實(shí)現(xiàn),C#更面向事件一點(diǎn),python應(yīng)該也有不錯的解決方案,繼續(xù)摸索...
以上內(nèi)容是小編給大家分享的Python實(shí)時(shí)獲取cmd的輸出的相關(guān)知識,希望大家喜歡。
相關(guān)文章
分布式訓(xùn)練training-operator和pytorch-distributed?RANK變量不統(tǒng)一解決
這篇文章主要介紹了分布式訓(xùn)練training-operator和pytorch-distributed?RANK變量不統(tǒng)一問題的解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
Python 解決相對路徑問題:"No such file or directory"
這篇文章主要介紹了Python 解決相對路徑問題:"No such file or directory"具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
Python安裝xarray庫讀取.nc文件的詳細(xì)步驟
大家應(yīng)該都知道庫xarray可以幫我們讀取出nc文件的內(nèi)容,所以下面這篇文章主要給大家介紹了關(guān)于Python安裝xarray讀取.nc文件的詳細(xì)步驟,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
pycharm運(yùn)行和調(diào)試不顯示結(jié)果的解決方法
今天小編就為大家分享一篇pycharm運(yùn)行和調(diào)試不顯示結(jié)果的解決方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11
python實(shí)現(xiàn)根據(jù)月份和日期得到星座的方法
這篇文章主要介紹了python實(shí)現(xiàn)根據(jù)月份和日期得到星座的方法,涉及Python操作字符串及數(shù)組的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03

