You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

104 lines
3.4 KiB

import subprocess
import json
import os
import time
from flask import Flask, render_template, request, Response, jsonify, redirect, url_for, session
from datetime import timedelta
from dotenv import load_dotenv
# Load biến môi trường từ file .env
load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv("SECRET_KEY", "default_secret_key") # Lấy từ .env hoặc đặt giá trị mặc định
app.permanent_session_lifetime = timedelta(days=1)
# Danh sách tài khoản & mật khẩu
USERS = {
"admin": "123456",
"user1": "password1",
"user2": "password2"
}
# Định nghĩa đường dẫn file JSON chứa danh sách service
SERVICES_FILE = os.path.join(os.path.dirname(__file__), "data", "services.json")
def load_services():
"""Đọc danh sách services từ file JSON"""
with open(SERVICES_FILE, "r", encoding="utf-8") as file:
return json.load(file)
@app.route("/")
def home():
"""Trang chủ: Hiển thị danh sách service (yêu cầu đăng nhập)"""
if "user" not in session:
return redirect(url_for("login"))
listService = [s for s in load_services() if s.get("status", "active") == "active"]
return render_template("index.html", listService=listService)
@app.route("/login", methods=["GET", "POST"])
def login():
"""Xử lý đăng nhập"""
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
if username in USERS and USERS[username] == password:
session["user"] = username
session.permanent = True
return redirect(url_for("home"))
else:
return render_template("login.html", error="Invalid username or password")
return render_template("login.html")
@app.route("/logout")
def logout():
"""Đăng xuất"""
session.pop("user", None)
return redirect(url_for("login"))
def run_shell_command(command_str):
"""Chạy một lệnh shell và gửi output theo thời gian thực"""
process = subprocess.Popen(command_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, executable="/bin/bash")
for line in iter(process.stdout.readline, ''):
yield f"data: {line.strip()}\n\n"
time.sleep(0.1)
for line in iter(process.stderr.readline, ''):
yield f"data: [] {line.strip()}\n\n"
time.sleep(0.1)
process.wait()
if process.returncode == 0:
yield f"data: SUCCESS\n\n"
else:
yield f"data: ERROR\n\n"
def generate_output(command_list):
"""Chạy command từ JSON, sau đó restart Nginx"""
command_str = " ".join(command_list)
yield from run_shell_command(command_str)
nginx_project_path = os.getenv("NGINX_PROJECT_PATH", "/projects/nginx")
nginx_command = f"cd {nginx_project_path} && docker compose down && docker compose up -d"
yield f"data: === Restarting Nginx ===\n\n"
yield from run_shell_command(nginx_command)
@app.route("/run-command", methods=["GET"])
def run_command():
"""API chạy command từ frontend"""
if "user" not in session:
return jsonify({"error": "Unauthorized"}), 401
command_list = request.args.getlist("command[]")
if not command_list:
return jsonify({"error": "No command provided"}), 400
return Response(generate_output(command_list), mimetype="text/event-stream")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)