ynsc133 commited on
Commit
326bcac
·
verified ·
1 Parent(s): 919db45

Create vps_monitor.py

Browse files
Files changed (1) hide show
  1. vps_monitor.py +187 -0
vps_monitor.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ logging.basicConfig(
15
+ level=logging.INFO,
16
+ format='%(asctime)s - %(levelname)s - %(message)s',
17
+ handlers=[
18
+ logging.StreamHandler(sys.stdout),
19
+ logging.StreamHandler(sys.stderr)
20
+ ]
21
+ )
22
+ logger = logging.getLogger()
23
+
24
+ def get_vps_configs():
25
+ configs = []
26
+ index = 1
27
+ while True:
28
+ hostname = os.environ.get(f'HOSTNAME_{index}')
29
+ if not hostname:
30
+ break
31
+
32
+ username = os.environ.get(f'USERNAME_{index}')
33
+ password = os.environ.get(f'PASSWORD_{index}')
34
+
35
+ script_paths = []
36
+ script_index = 1
37
+ while True:
38
+ script_path = os.environ.get(f'SCRIPT_PATHS_{index}_{script_index}')
39
+ if not script_path:
40
+ break
41
+ script_paths.append(script_path.strip())
42
+ script_index += 1
43
+
44
+ for script_path in script_paths:
45
+ configs.append({
46
+ 'index': index,
47
+ 'hostname': hostname,
48
+ 'username': username,
49
+ 'password': password,
50
+ 'script_path': script_path
51
+ })
52
+
53
+ index += 1
54
+ return configs
55
+
56
+ def check_and_run_script(config):
57
+ logger.info(f"Checking VPS {config['index']}: {config['hostname']} - {config['script_path']}")
58
+ client = None
59
+ try:
60
+ client = paramiko.SSHClient()
61
+ client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
62
+ client.connect(hostname=config['hostname'], username=config['username'], password=config['password'], port=22)
63
+
64
+ script_path = config['script_path']
65
+ script_name = os.path.basename(script_path)
66
+ key = f"{config['index']}:{config['hostname']}:{script_name}"
67
+
68
+ check_command = f"ps aux | grep '{script_path}' | grep -v grep"
69
+
70
+ stdin, stdout, stderr = client.exec_command(check_command)
71
+ output = stdout.read().decode('utf-8').strip()
72
+
73
+ if output and script_path in output:
74
+ status = "Running"
75
+ else:
76
+ logger.info(f"Script {script_name} not running. Attempting to restart.")
77
+ stdin, stdout, stderr = client.exec_command(f"nohup /bin/sh {script_path} > /dev/null 2>&1 & echo $!")
78
+ new_pid = stdout.read().decode('utf-8').strip()
79
+
80
+ if new_pid.isdigit():
81
+ status = "Restarted"
82
+ else:
83
+ status = "Restart Failed"
84
+
85
+ vps_status[key] = {
86
+ 'index': config['index'],
87
+ 'status': status,
88
+ 'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
89
+ 'username': config['username'],
90
+ 'script_name': script_name
91
+ }
92
+
93
+ except Exception as e:
94
+ logger.error(f"Error occurred while checking VPS {config['index']} - {config['hostname']} - {script_name}: {str(e)}")
95
+ vps_status[f"{config['index']}:{config['hostname']}:{script_name}"] = {
96
+ 'index': config['index'],
97
+ 'status': f"Error: {str(e)}",
98
+ 'last_check': time.strftime('%Y-%m-%d %H:%M:%S'),
99
+ 'username': config['username'],
100
+ 'script_name': script_name
101
+ }
102
+ finally:
103
+ if client:
104
+ client.close()
105
+
106
+ def check_all_vps():
107
+ logger.info("Starting VPS check")
108
+ for config in get_vps_configs():
109
+ check_and_run_script(config)
110
+
111
+ table = "+---------+-----------------------+------------------+----------+-------------------------+----------+\n"
112
+ table += "| Index | Hostname | Script Name | Status | Last Check | Username |\n"
113
+ table += "+---------+-----------------------+------------------+----------+-------------------------+----------+\n"
114
+
115
+ for key, status in vps_status.items():
116
+ index, hostname, script_name = key.split(':')
117
+ table += "| {:<7} | {:<21} | {:<16} | {:<8} | {:<23} | {:<8} |\n".format(
118
+ status['index'], hostname[:21], script_name[:16], status['status'][:8],
119
+ status['last_check'], status['username'][:8]
120
+ )
121
+ table += "+---------+-----------------------+------------------+----------+-------------------------+----------+\n"
122
+
123
+ logger.info("\n" + table)
124
+
125
+ @app.route('/')
126
+ def index():
127
+ html = '''
128
+ <h1>VPS Status Overview</h1>
129
+ <table border="1">
130
+ <tr>
131
+ <th>Index</th>
132
+ <th>Hostname</th>
133
+ <th>Script Name</th>
134
+ <th>Status</th>
135
+ <th>Last Check</th>
136
+ <th>Username</th>
137
+ </tr>
138
+ {% for key, data in vps_status.items() %}
139
+ <tr>
140
+ <td>{{ data.index }}</td>
141
+ <td><a href="/status/{{ key }}">{{ key.split(':')[1] }}</a></td>
142
+ <td>{{ data.script_name }}</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/<path:key>')
153
+ def vps_status_detail(key):
154
+ return jsonify(vps_status[key]) if key in vps_status else (jsonify({"error": "VPS or script not found"}), 404)
155
+
156
+ @app.route('/health')
157
+ def health_check():
158
+ return jsonify({"status": "healthy", "uptime": time.time() - start_time}), 200
159
+
160
+ def run_flask():
161
+ app.run(host='0.0.0.0', port=8080)
162
+
163
+ def main():
164
+ global start_time
165
+ start_time = time.time()
166
+
167
+ logger.info("===== VPS monitoring script is starting =====")
168
+
169
+ Thread(target=run_flask).start()
170
+ logger.info("Flask server started in background")
171
+
172
+ check_all_vps()
173
+ schedule.every(15).minutes.do(check_all_vps)
174
+ logger.info("Scheduled VPS check every 15 minutes")
175
+
176
+ logger.info("===== VPS monitoring script is running =====")
177
+
178
+ heartbeat_count = 0
179
+ while True:
180
+ schedule.run_pending()
181
+ time.sleep(60)
182
+ heartbeat_count += 1
183
+ if heartbeat_count % 5 == 0:
184
+ logger.info(f"Heartbeat: Script is still running. Uptime: {heartbeat_count} minutes")
185
+
186
+ if __name__ == "__main__":
187
+ main()