Add .deb agent package with systemd timer and interactive setup
This commit is contained in:
Executable
+146
@@ -0,0 +1,146 @@
|
||||
import psutil
|
||||
import socket
|
||||
import platform
|
||||
import time
|
||||
import os
|
||||
import getpass
|
||||
import json
|
||||
import requests
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(message)s",
|
||||
)
|
||||
|
||||
|
||||
def load_config():
|
||||
cfg_path = Path(__file__).with_suffix("").parent / "config.json"
|
||||
if cfg_path.exists():
|
||||
with open(cfg_path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
return {
|
||||
"server_url": "http://127.0.0.1",
|
||||
"agent_token": "agent-secret-token",
|
||||
"interval_minutes": 60,
|
||||
"send_public_ip": False,
|
||||
}
|
||||
|
||||
|
||||
def get_local_ip():
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.settimeout(1)
|
||||
s.connect(("8.8.8.8", 80))
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
return ip
|
||||
except Exception:
|
||||
return "127.0.0.1"
|
||||
|
||||
|
||||
def get_public_ip():
|
||||
try:
|
||||
r = requests.get("https://api.ipify.org", timeout=5)
|
||||
return r.text.strip()
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def get_uptime():
|
||||
return int(time.time() - psutil.boot_time())
|
||||
|
||||
|
||||
def get_disk_info():
|
||||
disks = []
|
||||
for part in psutil.disk_partitions(all=False):
|
||||
try:
|
||||
usage = psutil.disk_usage(part.mountpoint)
|
||||
disks.append({
|
||||
"device": part.device,
|
||||
"mountpoint": part.mountpoint,
|
||||
"total_gb": round(usage.total / (2**30), 1),
|
||||
"used_gb": round(usage.used / (2**30), 1),
|
||||
"free_gb": round(usage.free / (2**30), 1),
|
||||
"percent": usage.percent,
|
||||
})
|
||||
except Exception:
|
||||
continue
|
||||
return disks
|
||||
|
||||
|
||||
def get_cpu_temp():
|
||||
try:
|
||||
temps = psutil.sensors_temperatures()
|
||||
if temps:
|
||||
for name, entries in temps.items():
|
||||
for entry in entries:
|
||||
if entry.current:
|
||||
return round(entry.current, 1)
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def get_load_avg():
|
||||
try:
|
||||
return ", ".join(str(x) for x in os.getloadavg())
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def get_top_processes(limit=10):
|
||||
procs = []
|
||||
for p in psutil.process_iter(["pid", "name", "cpu_percent", "memory_percent"]):
|
||||
try:
|
||||
procs.append({
|
||||
"pid": p.info["pid"],
|
||||
"name": p.info["name"],
|
||||
"cpu_percent": round(p.info["cpu_percent"] or 0, 1),
|
||||
"ram_percent": round((p.info["memory_percent"] or 0), 1),
|
||||
})
|
||||
except Exception:
|
||||
continue
|
||||
procs.sort(key=lambda x: x["cpu_percent"], reverse=True)
|
||||
return procs[:limit]
|
||||
|
||||
|
||||
def collect():
|
||||
cfg = load_config()
|
||||
payload = {
|
||||
"hostname": socket.gethostname(),
|
||||
"username": getpass.getuser(),
|
||||
"os_info": f"{platform.system()} {platform.release()}",
|
||||
"local_ip": get_local_ip(),
|
||||
"public_ip": get_public_ip() if cfg.get("send_public_ip") else None,
|
||||
"uptime_sec": get_uptime(),
|
||||
"cpu_percent": psutil.cpu_percent(interval=1),
|
||||
"ram_percent": psutil.virtual_memory().percent,
|
||||
"ram_total_gb": round(psutil.virtual_memory().total / (2**30), 1),
|
||||
"disk_info": get_disk_info(),
|
||||
"cpu_temp": get_cpu_temp(),
|
||||
"load_avg": get_load_avg(),
|
||||
"processes": get_top_processes(10),
|
||||
}
|
||||
return payload, cfg
|
||||
|
||||
|
||||
def send(payload, cfg):
|
||||
url = cfg["server_url"].rstrip("/") + "/api/heartbeat"
|
||||
headers = {"Authorization": f"Bearer {cfg['agent_token']}", "Content-Type": "application/json"}
|
||||
try:
|
||||
resp = requests.post(url, json=payload, headers=headers, timeout=15)
|
||||
resp.raise_for_status()
|
||||
logging.info("Heartbeat sent: %s", resp.status_code)
|
||||
except Exception as e:
|
||||
logging.error("Failed to send heartbeat: %s", e)
|
||||
|
||||
|
||||
def main():
|
||||
payload, cfg = collect()
|
||||
send(payload, cfg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user