python 監(jiān)控服務(wù)器是否有人遠(yuǎn)程登錄(詳細(xì)思路+代碼)
起源
當(dāng)同一個遠(yuǎn)程服務(wù)器有多個人使用的時候,想知道服務(wù)器是否有人在用,我們不能直接的去登錄,因為這樣可能會把對方擠下來,這并不友好,所以這里提供一個監(jiān)控遠(yuǎn)程服務(wù)器是否有人連接的方式
思路
遇到這個問題,想著如何去解決
剛開始的時候,我是想通過一個主動的方式,去監(jiān)控到服務(wù)器是否有人連接,就是說當(dāng)我想要知道服務(wù)器是否有人連接,我通過一個運(yùn)行一個腳本程序,然后返回給我一個結(jié)果,事實證明,我并沒有通過這樣的思路解決這個問題
后來想以一個被動的方式來監(jiān)控,比如在服務(wù)器上裝載一個腳本,每5分鐘運(yùn)行一次腳本,來確定服務(wù)器上是否有人連接,不過這也比較消耗資源,后來想到一個方式,就是監(jiān)控服務(wù)器連接和斷開的行為,在每次服務(wù)器連接和斷開的時候,運(yùn)行腳本來知道服務(wù)器是否有人連接
放個流程圖

這里是一整套的監(jiān)控流程圖,包括服務(wù)器監(jiān)控和界面展示
實現(xiàn)
我們有了思路,接下來就是實現(xiàn)的問題
實現(xiàn)起來也比較簡單
但是我們需要解決幾個問題
- 如何知道服務(wù)器有沒有人連接?
- 如何監(jiān)控遠(yuǎn)程服務(wù)器的連接和斷開?
cmd命令netstat監(jiān)控3389端口
對于第一個問題,如何知道服務(wù)器有沒有人連接?
這里可以了解一下3389端口(遠(yuǎn)程桌面的服務(wù)端口)和netstat 命令,在windons服務(wù)器中,一般是一個遠(yuǎn)程連接的端口,就是說你可以監(jiān)控這個端口,來知道服務(wù)器有沒有人遠(yuǎn)程連接;而netstat (顯示協(xié)議統(tǒng)計和當(dāng)前 TCP/IP 網(wǎng)絡(luò)連接)是一個cmd命令,我們可以通過它來監(jiān)控端口情況
比如這里我們要監(jiān)控3389端口
我們先連接遠(yuǎn)程連接服務(wù)器,打開cmd命令窗口,輸入命令:netstat -n -p tcp | find ":3389"
我們就得到一個類似如這樣的結(jié)果
TCP 10.11.174.373:55311 16.21.315.55:3389 ESTABLISHED
這里有2個ip,一個10.11.174.373,這個是你本地的ip,一個16.21.315.55,這個就是你服務(wù)器的ip
但你在服務(wù)器上運(yùn)行這個命令的時候,如果有遠(yuǎn)程連接,那么就會得到這樣的一個結(jié)果(當(dāng)然,你自己連接的也算),當(dāng)沒有人連接的時候,就會得到一個空的,沒有任何連接情況
python腳本實現(xiàn)
這里的腳本,我們要實現(xiàn)3個功能:
- 獲取本地ip
- 獲取服務(wù)器連接狀態(tài)(ip)
- 相關(guān)數(shù)據(jù)存儲到數(shù)據(jù)庫
雖然我們使用netstat命令監(jiān)控3389端口的時候有本地的ip,但是這只是有遠(yuǎn)程連接的時候有ip信息,但是如果無人連接,那么就獲取不到,當(dāng)然,你也可以自填本地ip,不過這樣并不是很好
獲取本地ip,這里我們是用python中的socket函數(shù)來實現(xiàn)
socket.getaddrinfo(socket.gethostname(),None)[-1][-1][0]
后面的服務(wù)器連接,上面有說
數(shù)據(jù)庫存儲,也就不多做說明了,直接上下代碼(這里數(shù)據(jù)庫,請自行建好)
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : server_ip.py
@Time : 2020/04/23 10:08:15
@Author : 吉祥鳥
@GitHub : https://github.com/jixn-hu
@CSDN : https://me.csdn.net/qq_37462361
'''
import os
import re
import pyodbc
import time
import socket
def now_time():
"""
格式化返回當(dāng)前時間
:return:
"""
now = int(time.time())
local_time = time.localtime(now)
format_now = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
return format_now
def open_184_db(db="rreporttask"):
"""
開啟本地數(shù)據(jù)庫
:param db: 數(shù)據(jù)庫(默認(rèn)為rreporttask)
:return: 創(chuàng)建好的數(shù)據(jù)庫連接
"""
print(now_time(), '連接184數(shù)據(jù)庫%s' % db)
driver = 'SQL Server'
# 數(shù)據(jù)庫ip
serverName = '******'
# 登陸用戶名和密碼
userName = '******'
passWord = '******'
# 建立連接并獲取cursor
conn = pyodbc.connect(driver=driver, server=serverName,
user=userName, password=passWord, database=db, charset="gbk")
return conn
def insert_many(conn, items, table_name):
"""
多條數(shù)據(jù)插入到數(shù)據(jù)庫(注:插入的數(shù)據(jù)包含表里的關(guān)鍵字)
:param conn:數(shù)據(jù)庫
:param items:插入的數(shù)據(jù)列表字典(列表內(nèi)包含字典類型)
:param table_name:數(shù)據(jù)庫表名
:return:無
"""
print(now_time(), "更新數(shù)據(jù)表{}...".format(table_name))
# print(now_time(),"item:", items)
if items:
cursor = conn.cursor()
sql1 = "insert into %s" % table_name
sql2 = "("
sql3 = ") values("
sql4 = ")"
for key in items[0].keys(): # 拼接sql語句
sql2 += "%s," % key
sql3 += "?,"
# sql4 += "%s=values(%s)," % (key, key)
sql = sql1 + sql2[:-1] + sql3[:-1] + sql4
item_values = []
for item in items:
item_values.append(list(item.values()))
num = len(item_values)
# print(num)
print(now_time(), '一共需要處理數(shù)據(jù)%s條' % num)
# print(now_time(),"sql:", sql)
try:
for i in range(0, num, 1000):
a = min(num, 1000 + i)
# print(item_values[i:a])
cursor.executemany(sql, item_values[i:a])
conn.commit()
print(now_time(), "當(dāng)前已經(jīng)處理%s條數(shù)據(jù)" % a)
except Exception as e:
print(now_time(), '更新數(shù)據(jù)失敗,回滾')
print(e)
conn.rollback()
conn.close()
def main():
items = []
item = {}
time.sleep(1)
cmd = 'netstat -n -p tcp | find ":3389"'
command = os.popen(cmd)
r = command.read()
print(r)
zz = r.split("\n")[0].split()
if r=='':
ip = "0000"
else:
local_ip = zz[1]
local_ip = re.sub(r":.*$",'',local_ip)
ip = zz[2]
item["server_ip"]=socket.getaddrinfo(socket.gethostname(),None)[-1][-1][0] # 本地ip
item["sign_ip"] = ip
item["entrytime"] = now_time()
items.append(item)
print(item)
conn = open_184_db()
insert_many(conn,items,"server_sign")
if __name__ == "__main__":
main()
你可以把這個python腳本,打包成exe,然后放到服務(wù)器上,設(shè)置觸發(fā)條件,當(dāng)有人連接和斷開服務(wù)器的時候,運(yùn)行這個腳本
至于如何設(shè)置這個觸發(fā)器,這就是第二個問題了,如何監(jiān)控遠(yuǎn)程服務(wù)器的連接和斷開?
這里可以百度下,windons自帶的任務(wù)計劃程序,通過這個我們可以設(shè)置exe服務(wù)器連接和斷開的時,運(yùn)行exe腳本,放個圖,之后的自行摸索下

其實到這里,基本就是結(jié)束了,詳細(xì)的思路和主要的實現(xiàn),也都有了,我們可以直接查詢數(shù)據(jù)庫就能的知道服務(wù)器連接的情況
展示
不過后面為了更方便看,后面我自己又使用flask做了一個界面展示
就不多說明了
先放個成果圖

直接上代碼
server_sign.py:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : server_sign.py
@Time : 2020/04/07 10:47:52
@Author : 吉祥鳥
@GitHub : https://github.com/jixn-hu
@CSDN : https://me.csdn.net/qq_37462361
'''
import re
import pyodbc
import time
from flask import Flask,render_template
app=Flask(__name__)
def now_time():
"""
格式化返回當(dāng)前時間
:return:
"""
now = int(time.time())
local_time = time.localtime(now)
format_now = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
return format_now
def open_184_db(db="rreporttask"):
"""
開啟本地數(shù)據(jù)庫
:param db: 數(shù)據(jù)庫(默認(rèn)為rreporttask)
:return: 創(chuàng)建好的數(shù)據(jù)庫連接
"""
print(now_time(), '連接184數(shù)據(jù)庫%s' % db)
driver = 'SQL Server'
serverName = '******'
# 登陸用戶名和密碼
userName = '******'
passWord = '******'
# 建立連接并獲取cursor
conn = pyodbc.connect(driver=driver, server=serverName,
user=userName, password=passWord, database=db, charset="gbk")
return conn
def select_one(conn, sql="select ios_id from ios_main"):
"""
查詢信息
:param time:
:param type:
:return:
"""
print(now_time(), "正在查詢數(shù)據(jù)庫......")
cursor = conn.cursor()
try:
cursor.execute(sql)
result = cursor.fetchall()
conn.commit()
print(now_time(), "數(shù)據(jù)查詢成功")
return result
except:
print(now_time(), '更新數(shù)據(jù)失敗,回滾')
conn.rollback()
conn.close()
@app.route('/admin/<name>') # route() 裝飾器告訴 Flask 什么樣的URL 能觸發(fā)我們的函數(shù)
def hello_world(name):
conn = open_184_db()
data_back = {}
datas = select_one(conn,"select server_ip,sign_ip,entrytime from(select *,ROW_NUMBER()over(partition by server_ip order by entrytime desc)rank from rreporttask..server_sign) as z where rank=1 order by server_ip")
for data in datas:
if data[1]=='0000' or '3389' in data[1]:
data_back[data[0]]="未連接"
data[1]="無"
else:
data_back[data[0]]="連接ing"
# print(datas)
return render_template("login.html",name=name,datas=datas,data_back=data_back)
@app.route('/hal/<name>') # route() 裝飾器告訴 Flask 什么樣的URL 能觸發(fā)我們的函數(shù)
def hello_world1(name):
return "hellodd {}".format(name)
if __name__ == "__main__":
app.run(debug = True,host='0.0.0.0') # 用 run() 函數(shù)來讓應(yīng)用運(yùn)行在本地服務(wù)器上
login.html:
<html>
<!-- CSS goes in the document HEAD or added to your external stylesheet -->
<style type="text/css">
table.hovertable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #999999;
border-collapse: collapse;
}
table.hovertable th {
background-color:#c3dde0;
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
}
table.hovertable tr {
background-color:#d4e3e5;
}
table.hovertable td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
}
</style>
<body>
<h1>服務(wù)器登錄狀態(tài)查看</h1>
<table class="hovertable">
<tr>
<th>服務(wù)器ip</th>
<th>登錄ip</th>
<th>連接時間</th>
<th>連接狀態(tài)</th>
</tr>
{% for data in datas %}
<tr>
<td>{{ data[0] }}</td>
<td>{{ data[1] }}</td>
<td>{{ data[2] }}</td>
<td>{{ data_back[data[0]] }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
思維導(dǎo)圖
最后,放一個思維導(dǎo)圖,供參考

以上就是python 監(jiān)控服務(wù)器是否有人遠(yuǎn)程登錄(詳細(xì)思路+代碼)的詳細(xì)內(nèi)容,更多關(guān)于python 監(jiān)控服務(wù)器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python實現(xiàn)進(jìn)度條和系統(tǒng)通知的示例詳解
這篇文章主要和大家分享兩個有意思的Python小工具,可以優(yōu)雅地實現(xiàn)進(jìn)度條和系統(tǒng)通知,文中的示例代碼簡潔易懂,有需要的小伙伴快也跟隨小編一起學(xué)習(xí)一下2023-11-11
django 多對多表的創(chuàng)建和插入代碼實現(xiàn)
這篇文章主要介紹了django-多對多表的創(chuàng)建和插入代碼實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
50行Python代碼獲取高考志愿信息的實現(xiàn)方法
這篇文章主要介紹了50行Python代碼獲取高考志愿信息的實現(xiàn)方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07

