Files
dock/02
2025-11-05 21:43:05 +08:00

475 lines
12 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 增强版控制器客户端
# 支持后台运行、开机自启、进程管理
SERVER_IP="159.138.58.239" # 修改为你的服务器IP
SERVER_PORT=5555
CLIENT_PORT=5556
HEARTBEAT_INTERVAL=30
CONFIG_FILE="/etc/controller_client.conf"
PID_FILE="/var/run/controller_client.pid"
LOG_FILE="/var/log/controller_client.log"
SCRIPT_DIR="/opt/controller_scripts"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
print_color() {
echo -e "${2}${1}${NC}"
}
# 检查root权限
check_root() {
if [[ $EUID -ne 0 ]]; then
print_color "错误: 此操作需要root权限" "$RED"
exit 1
fi
}
# 安装依赖
install_dependencies() {
print_color "安装必要依赖..." "$YELLOW"
if command -v apt-get &> /dev/null; then
apt-get update
apt-get install -y netcat-traditional curl wget
elif command -v yum &> /dev/null; then
yum install -y nc curl wget
elif command -v dnf &> /dev/null; then
dnf install -y nc curl wget
elif command -v apk &> /dev/null; then
apk add netcat-openbsd curl wget
fi
}
# 获取系统信息
get_system_info() {
if [[ -f /etc/os-release ]]; then
local distro=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
local version=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"')
echo "$distro $version"
else
echo "unknown"
fi
}
# 生成客户端序列号
generate_serial() {
if [[ -f /etc/machine-id ]]; then
cat /etc/machine-id | md5sum | cut -c1-8
else
date +%s | sha256sum | base64 | head -c 8
fi
}
# 初始化配置
init_config() {
mkdir -p "$(dirname "$CONFIG_FILE")"
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$SCRIPT_DIR"
if [[ ! -f "$CONFIG_FILE" ]]; then
cat > "$CONFIG_FILE" << EOF
# 控制器客户端配置
SERVER_IP="$SERVER_IP"
SERVER_PORT="$SERVER_PORT"
CLIENT_PORT="$CLIENT_PORT"
HEARTBEAT_INTERVAL="$HEARTBEAT_INTERVAL"
LOG_FILE="$LOG_FILE"
PID_FILE="$PID_FILE"
EOF
fi
# 加载配置
source "$CONFIG_FILE"
# 设置变量
SERIAL=$(generate_serial)
HOSTNAME=$(hostname)
SYSTEM_INFO=$(get_system_info)
}
# 检查进程是否运行
is_running() {
if [[ -f "$PID_FILE" ]]; then
local pid=$(cat "$PID_FILE")
if kill -0 "$pid" 2>/dev/null; then
return 0
else
rm -f "$PID_FILE"
fi
fi
return 1
}
# 启动客户端
start_client() {
if is_running; then
print_color "客户端已经在运行 (PID: $(cat "$PID_FILE"))" "$YELLOW"
return 0
fi
print_color "启动控制器客户端..." "$GREEN"
# 后台运行主程序
{
echo $$ > "$PID_FILE"
trap "rm -f '$PID_FILE'; exit 0" INT TERM
# 主循环
while true; do
if main_loop; then
log "主循环正常结束,重新启动"
else
log "主循环异常结束10秒后重新启动"
sleep 10
fi
done
} &
local pid=$!
echo $pid > "$PID_FILE"
sleep 2
if is_running; then
print_color "客户端启动成功! PID: $pid" "$GREEN"
print_color "日志文件: $LOG_FILE" "$BLUE"
print_color "序列号: $SERIAL" "$BLUE"
else
print_color "客户端启动失败!" "$RED"
fi
}
# 停止客户端
stop_client() {
if ! is_running; then
print_color "客户端未在运行" "$YELLOW"
return 0
fi
local pid=$(cat "$PID_FILE")
print_color "停止客户端 (PID: $pid)..." "$GREEN"
kill "$pid" 2>/dev/null
sleep 2
if is_running; then
kill -9 "$pid" 2>/dev/null
sleep 1
fi
if is_running; then
print_color "无法停止客户端" "$RED"
return 1
else
rm -f "$PID_FILE"
print_color "客户端已停止" "$GREEN"
return 0
fi
}
# 重启客户端
restart_client() {
stop_client
sleep 2
start_client
}
# 查看状态
status_client() {
if is_running; then
local pid=$(cat "$PID_FILE")
print_color "客户端运行中 - PID: $pid" "$GREEN"
print_color "序列号: $SERIAL" "$BLUE"
print_color "服务器: $SERVER_IP:$SERVER_PORT" "$BLUE"
# 显示最近日志
echo
print_color "最近日志:" "$YELLOW"
tail -10 "$LOG_FILE" 2>/dev/null || echo "无日志文件"
else
print_color "客户端未运行" "$RED"
fi
}
# 查看日志
tail_log() {
if [[ -f "$LOG_FILE" ]]; then
tail -f "$LOG_FILE"
else
print_color "日志文件不存在: $LOG_FILE" "$RED"
fi
}
# 发送心跳包
send_heartbeat() {
local nc_cmd=$(command -v nc || command -v netcat)
if [[ -z "$nc_cmd" ]]; then
log "错误: netcat 未安装"
return 1
fi
if echo "HEARTBEAT|$SERIAL|$HOSTNAME|$SYSTEM_INFO" | timeout 10 $nc_cmd "$SERVER_IP" "$SERVER_PORT"; then
log "心跳包发送成功"
return 0
else
log "无法连接到服务器 $SERVER_IP:$SERVER_PORT"
return 1
fi
}
# 执行命令
execute_command() {
local command="$1"
log "执行命令: $command"
# 执行命令并记录结果
result=$(eval "$command" 2>&1)
log "命令结果: $result"
echo "$result"
}
# 执行脚本
execute_script() {
local script_name="$1"
case "$script_name" in
"shutdown")
print_color "执行关机命令..." "$RED"
log "执行关机命令"
shutdown -h now
;;
"reboot")
print_color "执行重启命令..." "$YELLOW"
log "执行重启命令"
reboot
;;
"restart_services")
print_color "重启系统服务..." "$YELLOW"
log "重启系统服务"
systemctl restart networking 2>/dev/null || systemctl restart network 2>/dev/null
systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null
;;
"system_info")
print_color "收集系统信息..." "$GREEN"
log "收集系统信息"
echo "=== 系统信息 ==="
echo "主机名: $HOSTNAME"
echo "序列号: $SERIAL"
echo "系统: $SYSTEM_INFO"
echo "内核: $(uname -r)"
echo "架构: $(uname -m)"
echo "上线时间: $(uptime -p 2>/dev/null || uptime)"
echo "内存使用:"
free -h 2>/dev/null || cat /proc/meminfo | head -5
echo "磁盘使用:"
df -h 2>/dev/null || df
;;
"update_system")
print_color "开始系统更新..." "$YELLOW"
log "开始系统更新"
if command -v apt-get &> /dev/null; then
apt-get update && apt-get upgrade -y
elif command -v yum &> /dev/null; then
yum update -y
elif command -v dnf &> /dev/null; then
dnf update -y
elif command -v apk &> /dev/null; then
apk update && apk upgrade
fi
echo "系统更新完成!"
;;
*)
log "未知脚本: $script_name"
echo "未知脚本: $script_name"
;;
esac
}
# 命令监听器
start_listener() {
local nc_cmd=$(command -v nc || command -v netcat)
if [[ -z "$nc_cmd" ]]; then
log "错误: netcat 未安装,无法启动监听器"
return 1
fi
while true; do
log "等待命令..."
command_data=$($nc_cmd -l -p "$CLIENT_PORT" -w 300 2>/dev/null)
if [[ -n "$command_data" ]]; then
log "收到命令: $command_data"
if echo "$command_data" | grep -q "^COMMAND:"; then
cmd=$(echo "$command_data" | cut -d: -f2-)
execute_command "$cmd"
elif echo "$command_data" | grep -q "^SCRIPT:"; then
script_name=$(echo "$command_data" | cut -d: -f2-)
execute_script "$script_name"
else
log "未知命令格式: $command_data"
fi
fi
sleep 1
done
}
# 主循环
main_loop() {
log "=== 控制器客户端启动 ==="
log "序列号: $SERIAL, 主机名: $HOSTNAME, 系统: $SYSTEM_INFO"
# 启动心跳包循环
while true; do
send_heartbeat
sleep "$HEARTBEAT_INTERVAL"
done &
local heartbeat_pid=$!
# 启动命令监听器
start_listener &
local listener_pid=$!
# 等待进程结束
wait $heartbeat_pid $listener_pid
kill $heartbeat_pid $listener_pid 2>/dev/null
return 0
}
# 安装系统服务
install_service() {
check_root
print_color "安装系统服务..." "$GREEN"
# 创建服务文件
local service_file="/etc/systemd/system/controller-client.service"
cat > "$service_file" << EOF
[Unit]
Description=Controller Client
After=network.target
Wants=network.target
[Service]
Type=forking
ExecStart=$(realpath "$0") start
ExecStop=$(realpath "$0") stop
ExecReload=$(realpath "$0") restart
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
EOF
# 重载systemd
systemctl daemon-reload
# 启用开机自启
systemctl enable controller-client
print_color "系统服务安装完成!" "$GREEN"
print_color "使用方法:" "$BLUE"
echo " systemctl start controller-client # 启动服务"
echo " systemctl stop controller-client # 停止服务"
echo " systemctl status controller-client # 查看状态"
echo " journalctl -u controller-client -f # 查看日志"
}
# 卸载系统服务
uninstall_service() {
check_root
print_color "卸载系统服务..." "$YELLOW"
systemctl stop controller-client 2>/dev/null
systemctl disable controller-client 2>/dev/null
rm -f /etc/systemd/system/controller-client.service
systemctl daemon-reload
print_color "系统服务已卸载" "$GREEN"
}
# 显示使用帮助
show_help() {
print_color "控制器客户端管理脚本" "$BLUE"
echo
echo "用法: $0 {start|stop|restart|status|log|install|uninstall|help}"
echo
echo "命令:"
echo " start - 启动客户端"
echo " stop - 停止客户端"
echo " restart - 重启客户端"
echo " status - 查看状态"
echo " log - 查看日志"
echo " install - 安装系统服务(开机自启)"
echo " uninstall - 卸载系统服务"
echo " help - 显示帮助"
echo
echo "示例:"
echo " $0 start # 启动客户端"
echo " $0 install # 安装系统服务"
echo " systemctl status controller-client # 查看服务状态"
}
# 主函数
main() {
init_config
case "${1:-}" in
"start")
check_root
start_client
;;
"stop")
check_root
stop_client
;;
"restart")
check_root
restart_client
;;
"status")
status_client
;;
"log")
tail_log
;;
"install")
install_dependencies
install_service
;;
"uninstall")
uninstall_service
;;
"help")
show_help
;;
*)
show_help
;;
esac
}
# 脚本入口
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi