chore: add docker-based cmd agent install script
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
#!/bin/sh
|
||||
# 此脚本在特权容器内运行,目标是安装CMD Agent到宿主机
|
||||
# 容器以 --privileged --pid=host -v /:/host 启动
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== 宿主机信息 ==="
|
||||
nsenter -t 1 -u hostname
|
||||
nsenter -t 1 -n ip addr show | grep "inet " | head -5
|
||||
|
||||
echo "=== 创建目录 ==="
|
||||
mkdir -p /host/opt/xiaoxia-cmd-agent
|
||||
|
||||
echo "=== 写入server.py ==="
|
||||
cat > /host/opt/xiaoxia-cmd-agent/server.py << 'PYEND'
|
||||
import http.server
|
||||
import subprocess
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
|
||||
TOKEN_FILE = "/etc/xiaoxia-cmd-agent.token"
|
||||
LOG_FILE = "/var/log/xiaoxia-cmd-agent.log"
|
||||
|
||||
def ensure_token():
|
||||
if not os.path.exists(TOKEN_FILE):
|
||||
os.makedirs(os.path.dirname(TOKEN_FILE), exist_ok=True)
|
||||
token = secrets.token_hex(16)
|
||||
with open(TOKEN_FILE, "w") as f:
|
||||
f.write(token)
|
||||
os.chmod(TOKEN_FILE, 0o600)
|
||||
with open(TOKEN_FILE) as f:
|
||||
return f.read().strip()
|
||||
|
||||
class CmdHandler(http.server.BaseHTTPRequestHandler):
|
||||
def log_message(self, fmt, *args):
|
||||
try:
|
||||
with open(LOG_FILE, "a") as f:
|
||||
f.write("%s - %s\n" % (self.address_string(), fmt % args))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def do_POST(self):
|
||||
if self.path == "/exec":
|
||||
auth = self.headers.get("Authorization", "")
|
||||
token = ensure_token()
|
||||
if auth != "xsa-" + token:
|
||||
self.send_response(401)
|
||||
self.end_headers()
|
||||
self.wfile.write(b"Unauthorized")
|
||||
return
|
||||
length = int(self.headers.get("Content-Length", 0))
|
||||
body = json.loads(self.rfile.read(length))
|
||||
cmd = body.get("command", "")
|
||||
timeout = body.get("timeout", 30)
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd, shell=True, capture_output=True, text=True,
|
||||
timeout=timeout
|
||||
)
|
||||
resp = {
|
||||
"exit_code": result.returncode,
|
||||
"stdout": result.stdout,
|
||||
"stderr": result.stderr
|
||||
}
|
||||
except subprocess.TimeoutExpired:
|
||||
resp = {"exit_code": -1, "stdout": "", "stderr": "timeout"}
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(resp).encode())
|
||||
elif self.path == "/status":
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({"status": "ok", "version": "1.0"}).encode())
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
|
||||
if __name__ == "__main__":
|
||||
ensure_token()
|
||||
server = http.server.HTTPServer(("0.0.0.0", 18888), CmdHandler)
|
||||
print("CMD Agent listening on 0.0.0.0:18888")
|
||||
server.serve_forever()
|
||||
PYEND
|
||||
|
||||
echo "=== 写入service文件 ==="
|
||||
cat > /host/etc/systemd/system/xiaoxia-cmd-agent.service << 'SVCEND'
|
||||
[Unit]
|
||||
Description=Xiaoxia CMD Agent
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 /opt/xiaoxia-cmd-agent/server.py
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
SVCEND
|
||||
|
||||
echo "=== 启动服务 ==="
|
||||
nsenter -t 1 -m -u -n -i systemctl daemon-reload
|
||||
nsenter -t 1 -m -u -n -i systemctl enable xiaoxia-cmd-agent
|
||||
nsenter -t 1 -m -u -n -i systemctl restart xiaoxia-cmd-agent
|
||||
sleep 2
|
||||
|
||||
echo "=== 服务状态 ==="
|
||||
nsenter -t 1 -m -u -n -i systemctl is-active xiaoxia-cmd-agent
|
||||
|
||||
echo "=== TOKEN ==="
|
||||
nsenter -t 1 -m -u -n -i cat /etc/xiaoxia-cmd-agent.token
|
||||
|
||||
echo "=== 测试 ==="
|
||||
nsenter -t 1 -m -u -n -i curl -s http://127.0.0.1:18888/status
|
||||
echo ""
|
||||
|
||||
echo "=== 完成 ==="
|
||||
Reference in New Issue
Block a user