gyc12 commited on
Commit
308a1fe
·
verified ·
1 Parent(s): c0740e3

Create vps_monitor.py

Browse files
Files changed (1) hide show
  1. vps_monitor.py +196 -0
vps_monitor.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import paramiko
2
+ import schedule
3
+ import time
4
+ import os
5
+ import sys
6
+ from flask import Flask, jsonify, render_template_string
7
+ from threading import Thread
8
+ import logging
9
+
10
+ app = Flask(__name__)
11
+
12
+ vps_status = {}
13
+
14
+ # 设置日志
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(levelname)s - %(message)s',
18
+ handlers=[
19
+ logging.StreamHandler(sys.stdout),
20
+ logging.StreamHandler(sys.stderr)
21
+ ]
22
+ )
23
+ logger = logging.getLogger()
24
+
25
+ def get_vps_configs():
26
+ configs = []
27
+ index = 1
28
+ while True:
29
+ hostname = os.environ.get(f'HOSTNAME_{index}')
30
+ if not hostname:
31
+ break
32
+
33
+ config = {
34
+ 'index': index,
35
+ 'hostname': hostname,
36
+ 'username': os.environ.get(f'USERNAME_{index}'),
37
+ 'password': os.environ.get(f'PASSWORD_{index}'),
38
+ 'script_path': os.environ.get(f'SCRIPT_PATH_{index}')
39
+ }
40
+ configs.append(config)
41
+
42
+ logger.info(f"Config {index}: {config['hostname']}, {config['username']}, {config['script_path']}")
43
+
44
+ index += 1
45
+ return configs
46
+
47
+ def check_and_run_script(config):
48
+ logger.info(f"Checking VPS {config['index']}: {config['hostname']}")
49
+ client = None
50
+ try:
51
+ client = paramiko.SSHClient()
52
+ client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
53
+
54
+ client.connect(
55
+ hostname=config['hostname'],
56
+ username=config['username'],
57
+ password=config['password'],
58
+ port=22
59
+ )
60
+
61
+ script_path = config['script_path']
62
+ script_name = os.path.basename(script_path)
63
+
64
+ check_command = f"ps -eo args | grep {script_name} | grep -v grep"
65
+
66
+ stdin, stdout, stderr = client.exec_command(check_command)
67
+ output = stdout.read().decode('utf-8').strip()
68
+
69
+ if output and script_path in output:
70
+ status = "Running"
71
+ logger.info(f"Script is running on {config['hostname']}")
72
+ else:
73
+ logger.info(f"Script not running on {config['hostname']}. Executing restart script.")
74
+ restart_command = f"nohup /bin/sh {script_path} > /dev/null 2>&1 &"
75
+ stdin, stdout, stderr = client.exec_command(restart_command)
76
+
77
+ status = "Restarted"
78
+ logger.info(f"Script restarted on {config['hostname']}")
79
+
80
+ vps_status[config['index']] = {
81
+ 'index': config['index'],
82
+ 'hostname': config['hostname'],
83
+ 'status': status,
84
+ 'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
85
+ 'username': config['username']
86
+ }
87
+
88
+ except Exception as e:
89
+ logger.error(f"Error occurred while checking VPS {config['index']} - {config['hostname']}: {str(e)}")
90
+ vps_status[config['index']] = {
91
+ 'index': config['index'],
92
+ 'hostname': config['hostname'],
93
+ 'status': f"Error: {str(e)}",
94
+ 'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
95
+ 'username': config['username']
96
+ }
97
+ finally:
98
+ if client:
99
+ client.close()
100
+
101
+ def check_all_vps():
102
+ logger.info("Starting VPS check")
103
+ vps_configs = get_vps_configs()
104
+ for config in vps_configs:
105
+ check_and_run_script(config)
106
+
107
+ # 创建表格头
108
+ table = "+---------+-----------------------+----------+-------------------------+----------+\n"
109
+ table += "| Index | Hostname | Status | Last Check | Username |\n"
110
+ table += "+---------+-----------------------+----------+-------------------------+----------+\n"
111
+
112
+ # 添加每个VPS的状态
113
+ for index in sorted(vps_status.keys()):
114
+ status = vps_status[index]
115
+ table += "| {:<7} | {:<21} | {:<8} | {:<23} | {:<8} |\n".format(
116
+ status['index'],
117
+ status['hostname'][:21],
118
+ status['status'][:8],
119
+ status['last_check'],
120
+ status['username'][:8]
121
+ )
122
+ table += "+---------+-----------------------+----------+-------------------------+----------+\n"
123
+
124
+ logger.info("\n" + table)
125
+
126
+ @app.route('/')
127
+ def index():
128
+ html = '''
129
+ <h1>VPS Status Overview</h1>
130
+ <table border="1">
131
+ <tr>
132
+ <th>Index</th>
133
+ <th>Hostname</th>
134
+ <th>Status</th>
135
+ <th>Last Check</th>
136
+ <th>Username</th>
137
+ </tr>
138
+ {% for index in vps_status.keys()|sort %}
139
+ {% set data = vps_status[index] %}
140
+ <tr>
141
+ <td>{{ data['index'] }}</td>
142
+ <td><a href="/status/{{ data['index'] }}">{{ data['hostname'] }}</a></td>
143
+ <td>{{ data['status'] }}</td>
144
+ <td>{{ data['last_check'] }}</td>
145
+ <td>{{ data['username'] }}</td>
146
+ </tr>
147
+ {% endfor %}
148
+ </table>
149
+ '''
150
+ return render_template_string(html, vps_status=vps_status)
151
+
152
+ @app.route('/status/<int:index>')
153
+ def vps_status_detail(index):
154
+ if index in vps_status:
155
+ return jsonify(vps_status[index])
156
+ else:
157
+ return jsonify({"error": "VPS not found"}), 404
158
+
159
+ @app.route('/health')
160
+ def health_check():
161
+ return jsonify({"status": "healthy", "uptime": time.time() - start_time}), 200
162
+
163
+ def run_flask():
164
+ app.run(host='0.0.0.0', port=8080)
165
+
166
+ def main():
167
+ global start_time
168
+ start_time = time.time()
169
+
170
+ logger.info("===== VPS monitoring script is starting =====")
171
+
172
+ flask_thread = Thread(target=run_flask)
173
+ flask_thread.start()
174
+ logger.info("Flask server started in background")
175
+
176
+ vps_configs = get_vps_configs()
177
+ logger.info(f"Found {len(vps_configs)} VPS configurations")
178
+
179
+ logger.info("Running initial VPS check")
180
+ check_all_vps()
181
+
182
+ schedule.every(15).minutes.do(check_all_vps)
183
+ logger.info("Scheduled VPS check every 15 minutes")
184
+
185
+ logger.info("===== VPS monitoring script is running =====")
186
+
187
+ heartbeat_count = 0
188
+ while True:
189
+ schedule.run_pending()
190
+ time.sleep(60)
191
+ heartbeat_count += 1
192
+ if heartbeat_count % 5 == 0: # 每5分钟输出一次心跳信息
193
+ logger.info(f"Heartbeat: Script is still running. Uptime: {heartbeat_count} minutes")
194
+
195
+ if __name__ == "__main__":
196
+ main()