Add active user session tracking from agent user :0 2026-07-16 15:46

user     pts/0        2026-07-16 15:50 (:0)
user     pts/1        2026-07-16 16:46 (:0)
user     pts/2        2026-07-17 09:05 (:0) to server UI
This commit is contained in:
2026-07-17 09:44:39 +07:00
parent 8e62eaf3f3
commit 7b2e5172ea
9 changed files with 195 additions and 5 deletions
+60 -1
View File
@@ -7,6 +7,7 @@ import getpass
import json
import requests
import logging
import subprocess
from pathlib import Path
logging.basicConfig(
@@ -70,6 +71,62 @@ def get_disk_info():
return disks
def get_active_sessions():
"""Return active user sessions similar to the `who` command.
Each session is a dict with keys: username, tty, login_time, origin.
Falls back to the current process user if `who` is unavailable.
"""
try:
result = subprocess.run(
["who", "-u"],
capture_output=True,
text=True,
timeout=5,
check=False,
)
if result.returncode != 0:
return []
sessions = []
for line in result.stdout.strip().splitlines():
line = line.strip()
if not line:
continue
parts = line.split()
if len(parts) < 5:
continue
username = parts[0]
tty = parts[1]
# login time is usually "YYYY-MM-DD HH:MM" (parts[2] and parts[3])
login_time = " ".join(parts[2:4]) if len(parts) >= 4 else ""
# The last field may be a comment in parentheses, e.g. (192.168.255.50)
origin = ""
if parts[-1].startswith("(") and parts[-1].endswith(")"):
origin = parts[-1][1:-1]
sessions.append({
"username": username,
"tty": tty,
"login_time": login_time,
"origin": origin,
})
return sessions
except Exception:
return []
def get_display_username(sessions):
"""Return a short username representation for the dashboard.
Single user -> username
Multiple -> comma-separated usernames
No sessions -> fallback to process user
"""
usernames = [s["username"] for s in sessions if s.get("username")]
if not usernames:
return getpass.getuser()
return ", ".join(dict.fromkeys(usernames))
def get_cpu_temp():
try:
temps = psutil.sensors_temperatures()
@@ -108,9 +165,11 @@ def get_top_processes(limit=10):
def collect():
cfg = load_config()
sessions = get_active_sessions()
payload = {
"hostname": socket.gethostname(),
"username": getpass.getuser(),
"username": get_display_username(sessions),
"sessions": sessions,
"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,