knbn commited on
Commit
3969f6a
·
verified ·
1 Parent(s): ead14c3

Create vps_monitor.py

Browse files
Files changed (1) hide show
  1. vps_monitor.py +192 -0
vps_monitor.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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['hostname']] = {
81
+ 'index': config['index'],
82
+ 'status': status,
83
+ 'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
84
+ 'username': config['username']
85
+ }
86
+
87
+ except Exception as e:
88
+ logger.error(f"Error occurred while checking VPS {config['index']} - {config['hostname']}: {str(e)}")
89
+ vps_status[config['hostname']] = {
90
+ 'index': config['index'],
91
+ 'status': f"Error: {str(e)}",
92
+ 'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
93
+ 'username': config['username']
94
+ }
95
+ finally:
96
+ if client:
97
+ client.close()
98
+
99
+ def check_all_vps():
100
+ logger.info("Starting VPS check")
101
+ vps_configs = get_vps_configs()
102
+ for config in vps_configs:
103
+ check_and_run_script(config)
104
+
105
+ # 创建表格头
106
+ table = "+---------+-----------------------+----------+-------------------------+----------+\n"
107
+ table += "| Index | Hostname | Status | Last Check | Username |\n"
108
+ table += "+---------+-----------------------+----------+-------------------------+----------+\n"
109
+
110
+ # 添加每个VPS的状态
111
+ for hostname, status in vps_status.items():
112
+ table += "| {:<7} | {:<21} | {:<8} | {:<23} | {:<8} |\n".format(
113
+ status['index'],
114
+ hostname[:21],
115
+ status['status'][:8],
116
+ status['last_check'],
117
+ status['username'][:8]
118
+ )
119
+ table += "+---------+-----------------------+----------+-------------------------+----------+\n"
120
+
121
+ logger.info("\n" + table)
122
+
123
+ @app.route('/')
124
+ def index():
125
+ html = '''
126
+ <h1>VPS Status Overview</h1>
127
+ <table border="1">
128
+ <tr>
129
+ <th>Index</th>
130
+ <th>Hostname</th>
131
+ <th>Status</th>
132
+ <th>Last Check</th>
133
+ <th>Username</th>
134
+ </tr>
135
+ {% for hostname, data in vps_status.items() %}
136
+ <tr>
137
+ <td>{{ data.index }}</td>
138
+ <td><a href="/status/{{ hostname }}">{{ hostname }}</a></td>
139
+ <td>{{ data.status }}</td>
140
+ <td>{{ data.last_check }}</td>
141
+ <td>{{ data.username }}</td>
142
+ </tr>
143
+ {% endfor %}
144
+ </table>
145
+ '''
146
+ return render_template_string(html, vps_status=vps_status)
147
+
148
+ @app.route('/status/<hostname>')
149
+ def vps_status_detail(hostname):
150
+ if hostname in vps_status:
151
+ return jsonify(vps_status[hostname])
152
+ else:
153
+ return jsonify({"error": "VPS not found"}), 404
154
+
155
+ @app.route('/health')
156
+ def health_check():
157
+ return jsonify({"status": "healthy", "uptime": time.time() - start_time}), 200
158
+
159
+ def run_flask():
160
+ app.run(host='0.0.0.0', port=8080)
161
+
162
+ def main():
163
+ global start_time
164
+ start_time = time.time()
165
+
166
+ logger.info("===== VPS monitoring script is starting =====")
167
+
168
+ flask_thread = Thread(target=run_flask)
169
+ flask_thread.start()
170
+ logger.info("Flask server started in background")
171
+
172
+ vps_configs = get_vps_configs()
173
+ logger.info(f"Found {len(vps_configs)} VPS configurations")
174
+
175
+ logger.info("Running initial VPS check")
176
+ check_all_vps()
177
+
178
+ schedule.every(15).minutes.do(check_all_vps)
179
+ logger.info("Scheduled VPS check every 15 minutes")
180
+
181
+ logger.info("===== VPS monitoring script is running =====")
182
+
183
+ heartbeat_count = 0
184
+ while True:
185
+ schedule.run_pending()
186
+ time.sleep(60)
187
+ heartbeat_count += 1
188
+ if heartbeat_count % 5 == 0: # 每5分钟输出一次心跳信息
189
+ logger.info(f"Heartbeat: Script is still running. Uptime: {heartbeat_count} minutes")
190
+
191
+ if __name__ == "__main__":
192
+ main()