Files
dock/01
2025-11-05 21:18:54 +08:00

322 lines
8.4 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
# 服务器控制器脚本 - 监听端口5555
# 支持: Debian, Ubuntu, CentOS, RHEL, Fedora, Alpine
SERVER_PORT=5555
LOG_FILE="/var/log/controller_server.log"
CLIENTS_FILE="/var/lib/controller_clients.txt"
SCRIPT_DIR="/opt/controller_scripts"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
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() {
local distro=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
case $distro in
debian|ubuntu)
apt-get update
apt-get install -y net-tools iproute2
;;
centos|rhel|fedora)
yum install -y net-tools iproute2 || dnf install -y net-tools iproute2
;;
alpine)
apk add net-tools iproute2
;;
*)
log "未知发行版请手动安装net-tools和iproute2"
;;
esac
}
# 初始化环境
initialize() {
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$(dirname "$CLIENTS_FILE")"
mkdir -p "$SCRIPT_DIR"
# 创建示例脚本
create_sample_scripts
touch "$LOG_FILE"
touch "$CLIENTS_FILE"
print_color "初始化完成!" "$GREEN"
}
create_sample_scripts() {
# 关机脚本
cat > "$SCRIPT_DIR/shutdown.sh" << 'EOF'
#!/bin/bash
echo "执行关机操作..."
shutdown -h now
EOF
# 重启脚本
cat > "$SCRIPT_DIR/reboot.sh" << 'EOF'
#!/bin/bash
echo "执行重启操作..."
reboot
EOF
# 服务重启脚本
cat > "$SCRIPT_DIR/restart_services.sh" << 'EOF'
#!/bin/bash
echo "重启网络服务..."
systemctl restart networking 2>/dev/null || systemctl restart network 2>/dev/null
echo "重启SSH服务..."
systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null
EOF
# 无限重启脚本 (危险)
cat > "$SCRIPT_DIR/reboot_loop.sh" << 'EOF'
#!/bin/bash
echo "设置无限重启 - 危险操作!"
(crontab -l 2>/dev/null; echo "*/5 * * * * /sbin/reboot") | crontab -
reboot
EOF
# 取消无限重启
cat > "$SCRIPT_DIR/cancel_loop.sh" << 'EOF'
#!/bin/bash
echo "取消无限重启..."
crontab -l | grep -v reboot | crontab -
echo "已取消计划重启任务"
EOF
chmod +x "$SCRIPT_DIR"/*.sh
}
# 显示客户端列表
show_clients() {
if [[ ! -s "$CLIENTS_FILE" ]]; then
print_color "没有已连接的客户端" "$YELLOW"
return
fi
print_color "已连接的客户端列表:" "$BLUE"
print_color "序列号 | IP地址 | 主机名 | 系统信息 | 最后在线" "$BLUE"
print_color "------------------------------------------------------------" "$BLUE"
cat "$CLIENTS_FILE"
}
# 向客户端发送命令
send_command() {
local serial=$1
local command=$2
if [[ -z "$serial" || -z "$command" ]]; then
print_color "用法: send <序列号> <命令>" "$RED"
return
fi
local client_info=$(grep "^$serial|" "$CLIENTS_FILE")
if [[ -z "$client_info" ]]; then
print_color "错误: 未找到序列号 $serial 的客户端" "$RED"
return
fi
IFS='|' read -r serial ip hostname system last_seen <<< "$client_info"
print_color "向客户端 $serial ($hostname) 发送命令: $command" "$GREEN"
# 发送命令到客户端
echo "COMMAND:$command" | nc -w 5 "$ip" 5556
if [[ $? -eq 0 ]]; then
print_color "命令发送成功!" "$GREEN"
else
print_color "命令发送失败!" "$RED"
fi
}
# 广播命令到所有客户端
broadcast_command() {
local command=$1
if [[ -z "$command" ]]; then
print_color "用法: broadcast <命令>" "$RED"
return
fi
print_color "向所有客户端广播命令: $command" "$YELLOW"
while IFS='|' read -r serial ip hostname system last_seen; do
if [[ -n "$serial" ]]; then
echo "$serial 发送命令..."
echo "COMMAND:$command" | nc -w 3 "$ip" 5556
fi
done < "$CLIENTS_FILE"
}
# 执行本地脚本
execute_script() {
local serial=$1
local script_name=$2
if [[ -z "$serial" || -z "$script_name" ]]; then
print_color "用法: script <序列号> <脚本名>" "$RED"
print_color "可用脚本:" "$BLUE"
ls "$SCRIPT_DIR"/*.sh | xargs -n 1 basename
return
fi
local script_path="$SCRIPT_DIR/$script_name"
if [[ ! -f "$script_path" ]]; then
print_color "错误: 脚本 $script_name 不存在" "$RED"
return
fi
local client_info=$(grep "^$serial|" "$CLIENTS_FILE")
if [[ -z "$client_info" ]]; then
print_color "错误: 未找到序列号 $serial 的客户端" "$RED"
return
fi
IFS='|' read -r serial ip hostname system last_seen <<< "$client_info"
print_color "向客户端 $serial 发送脚本: $script_name" "$GREEN"
# 发送脚本执行命令
echo "SCRIPT:$script_name" | nc -w 5 "$ip" 5556
}
# 启动服务器
start_server() {
print_color "启动控制器服务器在端口 $SERVER_PORT..." "$GREEN"
print_color "服务器日志: $LOG_FILE" "$BLUE"
print_color "客户端列表: $CLIENTS_FILE" "$BLUE"
while true; do
log "等待客户端连接..."
nc -l -p $SERVER_PORT -c '
client_ip=$(echo $SSH_CLIENT | awk "{print \$1}")
read -r data
timestamp=$(date "+%Y-%m-%d %H:%M:%S")
if echo "$data" | grep -q "HEARTBEAT|"; then
IFS="|" read -r heartbeat serial hostname system <<< "$data"
# 更新或添加客户端信息
grep -v "^$serial|" /var/lib/controller_clients.txt > /tmp/clients.tmp
echo "$serial|$client_ip|$hostname|$system|$timestamp" >> /tmp/clients.tmp
mv /tmp/clients.tmp /var/lib/controller_clients.txt
echo "ACK:OK"
else
echo "ACK:UNKNOWN_COMMAND"
fi
'
sleep 1
done
}
# 显示帮助
show_help() {
print_color "服务器控制器命令:" "$BLUE"
echo "list - 显示客户端列表"
echo "send - 向指定客户端发送命令"
echo "broadcast - 向所有客户端广播命令"
echo "script - 执行预定义脚本"
echo "scripts - 显示可用脚本"
echo "start - 启动服务器"
echo "stop - 停止服务器"
echo "status - 显示服务器状态"
echo "help - 显示此帮助"
}
# 主菜单
main_menu() {
print_color "=== 跨平台服务器控制器 ===" "$BLUE"
echo "1. 启动服务器"
echo "2. 显示客户端列表"
echo "3. 发送命令到客户端"
echo "4. 广播命令到所有客户端"
echo "5. 执行脚本"
echo "6. 显示可用脚本"
echo "7. 服务器状态"
echo "8. 退出"
read -p "请选择操作 [1-8]: " choice
case $choice in
1)
start_server
;;
2)
show_clients
;;
3)
read -p "输入序列号: " serial
read -p "输入命令: " command
send_command "$serial" "$command"
;;
4)
read -p "输入广播命令: " command
broadcast_command "$command"
;;
5)
read -p "输入序列号: " serial
read -p "输入脚本名: " script
execute_script "$serial" "$script"
;;
6)
print_color "可用脚本:" "$BLUE"
ls "$SCRIPT_DIR"/*.sh | xargs -n 1 basename
;;
7)
print_color "服务器状态:" "$BLUE"
pgrep -f "nc -l -p $SERVER_PORT" >/dev/null && \
print_color "服务器运行中" "$GREEN" || \
print_color "服务器未运行" "$RED"
;;
8)
print_color "再见!" "$GREEN"
exit 0
;;
*)
print_color "无效选择!" "$RED"
;;
esac
echo
main_menu
}
# 脚本入口
case "${1:-}" in
start)
check_root
install_dependencies
initialize
start_server
;;
*)
check_root
install_dependencies
initialize
main_menu
;;
esac