107 lines
2.9 KiB
Python
107 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
import time
|
|
import schedule
|
|
import logging
|
|
import subprocess
|
|
import fcntl
|
|
from pathlib import Path
|
|
from paths import *
|
|
|
|
logging.basicConfig(
|
|
level=logging.WARNING,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
handlers=[
|
|
logging.FileHandler("/var/log/hysteria_scheduler.log"),
|
|
logging.StreamHandler()
|
|
]
|
|
)
|
|
logger = logging.getLogger("HysteriaScheduler")
|
|
|
|
# Constants
|
|
BASE_DIR = Path("/etc/hysteria")
|
|
VENV_ACTIVATE = BASE_DIR / "hysteria2_venv/bin/activate"
|
|
LOCK_FILE = "/tmp/hysteria_scheduler.lock"
|
|
|
|
def acquire_lock():
|
|
try:
|
|
lock_fd = open(LOCK_FILE, 'w')
|
|
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
return lock_fd
|
|
except IOError:
|
|
logger.warning("Another process is already running and has the lock")
|
|
return None
|
|
|
|
def release_lock(lock_fd):
|
|
if lock_fd:
|
|
fcntl.flock(lock_fd, fcntl.LOCK_UN)
|
|
lock_fd.close()
|
|
|
|
def run_command(command, log_success=False):
|
|
activate_cmd = f"source {VENV_ACTIVATE}"
|
|
full_cmd = f"{activate_cmd} && {command}"
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
full_cmd,
|
|
shell=True,
|
|
executable="/bin/bash",
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
logger.error(f"Command failed: {full_cmd}")
|
|
logger.error(f"Error: {result.stderr}")
|
|
elif log_success:
|
|
logger.info(f"Command executed successfully: {full_cmd}")
|
|
|
|
return result.returncode == 0
|
|
except Exception as e:
|
|
logger.exception(f"Exception running command: {full_cmd}")
|
|
return False
|
|
|
|
def check_traffic_status():
|
|
lock_fd = acquire_lock()
|
|
if not lock_fd:
|
|
return
|
|
|
|
try:
|
|
success = run_command(f"python3 {CLI_PATH} traffic-status --no-gui", log_success=False)
|
|
if not success:
|
|
pass
|
|
finally:
|
|
release_lock(lock_fd)
|
|
|
|
def backup_hysteria():
|
|
lock_fd = acquire_lock()
|
|
if not lock_fd:
|
|
logger.warning("Skipping backup due to lock")
|
|
return
|
|
|
|
try:
|
|
run_command(f"python3 {CLI_PATH} backup-hysteria", log_success=True)
|
|
finally:
|
|
release_lock(lock_fd)
|
|
|
|
def main():
|
|
logger.info("Starting Hysteria Scheduler")
|
|
|
|
schedule.every(1).minutes.do(check_traffic_status)
|
|
schedule.every(6).hours.do(backup_hysteria)
|
|
|
|
check_traffic_status()
|
|
backup_hysteria()
|
|
|
|
while True:
|
|
try:
|
|
schedule.run_pending()
|
|
time.sleep(1)
|
|
except KeyboardInterrupt:
|
|
logger.info("Shutting down scheduler")
|
|
break
|
|
except Exception as e:
|
|
logger.exception("Error in main loop")
|
|
time.sleep(60)
|
|
|
|
if __name__ == "__main__":
|
|
main() |