364 lines
10 KiB
Bash
364 lines
10 KiB
Bash
#!/bin/bash
|
||
|
||
# 核云IDC服务商VPS自动监测重启程序 - 安装脚本
|
||
# 该脚本会检查配置并创建systemd服务,持续化运行monitor.py
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 获取当前脚本所在目录的绝对路径
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
# 定义服务名称
|
||
SERVICE_NAME="idc-monitor"
|
||
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
|
||
CONFIG_FILE="${SCRIPT_DIR}/config.yml"
|
||
|
||
echo "=========================================="
|
||
echo " 核云IDC VPS监控程序 - 安装向导"
|
||
echo "=========================================="
|
||
echo ""
|
||
|
||
# 检查是否以root权限运行
|
||
if [ "$EUID" -ne 0 ]; then
|
||
echo -e "${RED}错误: 请以root权限运行此脚本 (sudo ./install.sh)${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查Python是否已安装
|
||
if ! command -v python3 &> /dev/null; then
|
||
if command -v python &> /dev/null; then
|
||
PYTHON_CMD="python"
|
||
else
|
||
echo -e "${RED}错误: 未找到Python,请先安装Python 3${NC}"
|
||
exit 1
|
||
fi
|
||
else
|
||
PYTHON_CMD="python3"
|
||
fi
|
||
|
||
echo -e "${GREEN}✅${NC} 检测到Python: ${PYTHON_CMD}"
|
||
|
||
# 检查pip是否存在
|
||
if command -v pip3 &> /dev/null; then
|
||
PIP_CMD="pip3"
|
||
elif command -v pip &> /dev/null; then
|
||
PIP_CMD="pip"
|
||
else
|
||
echo -e "${YELLOW}警告: 未检测到pip${NC}"
|
||
read -p "是否现在安装pip?(Y/n): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||
echo -e "${RED}错误: pip不可用,无法继续${NC}"
|
||
exit 1
|
||
else
|
||
# 安装pip
|
||
if command -v apt-get &> /dev/null; then
|
||
apt-get update && apt-get install -y python3-pip
|
||
elif command -v yum &> /dev/null; then
|
||
yum install -y python3-pip
|
||
elif command -v dnf &> /dev/null; then
|
||
dnf install -y python3-pip
|
||
else
|
||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
|
||
${PYTHON_CMD} get-pip.py
|
||
rm -f get-pip.py
|
||
fi
|
||
|
||
if command -v pip3 &> /dev/null; then
|
||
PIP_CMD="pip3"
|
||
elif command -v pip &> /dev/null; then
|
||
PIP_CMD="pip"
|
||
else
|
||
echo -e "${RED}错误: pip安装失败${NC}"
|
||
exit 1
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
echo -e "${GREEN}✅${NC} 检测到pip: ${PIP_CMD}"
|
||
|
||
# 检查配置文件是否存在
|
||
if [ ! -f "${CONFIG_FILE}" ]; then
|
||
echo -e "${RED}错误: 配置文件不存在: ${CONFIG_FILE}${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# 读取现有配置
|
||
echo ""
|
||
echo "正在检查配置文件..."
|
||
|
||
# 使用grep解析YAML配置
|
||
ACCOUNT=$(grep "^ACCOUNT:" "${CONFIG_FILE}" | sed 's/ACCOUNT:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d "'" | tr -d '"')
|
||
API_KEY=$(grep "^API_KEY:" "${CONFIG_FILE}" | sed 's/API_KEY:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d "'" | tr -d '"')
|
||
WAY=$(grep "^WAY:" "${CONFIG_FILE}" | sed 's/WAY:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d "'" | tr -d '"')
|
||
DOMAIN=$(grep "^DOMAIN:" "${CONFIG_FILE}" | sed 's/DOMAIN:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d "'" | tr -d '"')
|
||
SPAN=$(grep "^SPAN:" "${CONFIG_FILE}" | sed 's/SPAN:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d "'" | tr -d '"')
|
||
EXCEPTION_IPS=$(grep "^EXCEPTION_IPS:" "${CONFIG_FILE}" | sed 's/EXCEPTION_IPS:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d "'" | tr -d '"')
|
||
|
||
NEED_UPDATE=false
|
||
|
||
# 检查ACCOUNT
|
||
if [ -z "$ACCOUNT" ]; then
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e -n "${RED}请输入核云IDC账号(手机号或邮箱): ${NC}"
|
||
read ACCOUNT
|
||
if [ -z "$ACCOUNT" ]; then
|
||
echo -e "${RED}错误: 账号不能为空${NC}"
|
||
exit 1
|
||
fi
|
||
NEED_UPDATE=true
|
||
fi
|
||
|
||
# 检查API_KEY
|
||
if [ -z "$API_KEY" ]; then
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e -n "${RED}请输入核云IDC API密钥: ${NC}"
|
||
read API_KEY
|
||
if [ -z "$API_KEY" ]; then
|
||
echo -e "${RED}错误: API密钥不能为空${NC}"
|
||
exit 1
|
||
fi
|
||
NEED_UPDATE=true
|
||
fi
|
||
|
||
# 检查WAY
|
||
if [ -z "$WAY" ]; then
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e "${RED}请选择检测方式:${NC}"
|
||
echo " 1. ping - Ping检测IP地址(默认)"
|
||
echo " 2. http - HTTP检测域名"
|
||
echo -e -n "${RED}请输入选项 1/2,直接回车默认为1: ${NC}"
|
||
read WAY_CHOICE
|
||
|
||
if [ "$WAY_CHOICE" = "2" ]; then
|
||
WAY="http"
|
||
else
|
||
WAY="ping"
|
||
fi
|
||
NEED_UPDATE=true
|
||
fi
|
||
|
||
# 如果WAY为http,检查DOMAIN
|
||
if [ "$WAY" = "http" ] && [ -z "$DOMAIN" ]; then
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e "${RED}请输入要检测的域名(多个域名用英文逗号分隔):${NC}"
|
||
echo "例如: example.com,test.com,demo.com"
|
||
echo -e -n "${RED}域名: ${NC}"
|
||
read DOMAIN
|
||
if [ -z "$DOMAIN" ]; then
|
||
echo -e "${RED}错误: 域名不能为空${NC}"
|
||
exit 1
|
||
fi
|
||
NEED_UPDATE=true
|
||
fi
|
||
|
||
# 检查SPAN
|
||
if [ -z "$SPAN" ]; then
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e -n "${RED}请输入监控间隔时间(秒,直接回车默认300秒): ${NC}"
|
||
read SPAN_INPUT
|
||
if [ -n "$SPAN_INPUT" ]; then
|
||
if [[ "$SPAN_INPUT" =~ ^[0-9]+$ ]]; then
|
||
if [ "$SPAN_INPUT" -lt 60 ]; then
|
||
echo -e "${RED}警告: 间隔时间过短,建议至少60秒${NC}"
|
||
fi
|
||
SPAN=$SPAN_INPUT
|
||
else
|
||
echo -e "${RED}警告: 输入无效,使用默认值300秒${NC}"
|
||
SPAN=300
|
||
fi
|
||
else
|
||
SPAN=300
|
||
fi
|
||
NEED_UPDATE=true
|
||
fi
|
||
|
||
# 询问是否设置例外IP
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e "${RED}是否设置例外IP列表?(这些IP关机时不会自动开机)${NC}"
|
||
echo -e -n "${RED}请输入例外IP,多个IP用英文逗号分隔,直接回车跳过: ${NC}"
|
||
read EXCEPTION_INPUT
|
||
|
||
if [ -n "$EXCEPTION_INPUT" ]; then
|
||
EXCEPTION_IPS="$EXCEPTION_INPUT"
|
||
NEED_UPDATE=true
|
||
else
|
||
if [ -z "$EXCEPTION_IPS" ]; then
|
||
EXCEPTION_IPS=""
|
||
fi
|
||
fi
|
||
|
||
# 保存配置
|
||
if [ "$NEED_UPDATE" = true ]; then
|
||
echo ""
|
||
echo "=================================================="
|
||
|
||
# 使用Python更新YAML文件
|
||
${PYTHON_CMD} << PYEOF
|
||
import yaml
|
||
|
||
config_file = "${CONFIG_FILE}"
|
||
|
||
try:
|
||
with open(config_file, 'r', encoding='utf-8') as f:
|
||
config = yaml.safe_load(f)
|
||
except:
|
||
config = {}
|
||
|
||
config['ACCOUNT'] = "${ACCOUNT}"
|
||
config['API_KEY'] = "${API_KEY}"
|
||
config['WAY'] = "${WAY}"
|
||
if "${WAY}" == "http":
|
||
config['DOMAIN'] = "${DOMAIN}"
|
||
config['SPAN'] = ${SPAN}
|
||
|
||
# 处理例外IP
|
||
exception_ips_str = "${EXCEPTION_IPS}"
|
||
if exception_ips_str:
|
||
config['EXCEPTION_IPS'] = [ip.strip() for ip in exception_ips_str.split(',') if ip.strip()]
|
||
else:
|
||
config['EXCEPTION_IPS'] = []
|
||
|
||
# 清除JWT字段(重新生成)
|
||
if 'JWT' in config:
|
||
del config['JWT']
|
||
|
||
with open(config_file, 'w', encoding='utf-8') as f:
|
||
yaml.dump(config, f, allow_unicode=True, default_flow_style=False)
|
||
|
||
print("\033[32m✅ 配置已保存\033[0m")
|
||
PYEOF
|
||
|
||
if [ $? -ne 0 ]; then
|
||
echo -e "${RED}错误: 配置保存失败${NC}"
|
||
exit 1
|
||
fi
|
||
else
|
||
echo -e "${GREEN}✅${NC} 配置检查完成,无需更新"
|
||
fi
|
||
|
||
echo ""
|
||
echo "当前配置:"
|
||
echo " 账号: ${ACCOUNT}"
|
||
echo " 检测方式: ${WAY}"
|
||
if [ "$WAY" = "http" ]; then
|
||
echo " 域名: ${DOMAIN}"
|
||
fi
|
||
echo " 监控间隔: ${SPAN}秒"
|
||
if [ -n "$EXCEPTION_IPS" ]; then
|
||
echo " 例外IP: ${EXCEPTION_IPS}"
|
||
else
|
||
echo " 例外IP: 无"
|
||
fi
|
||
echo ""
|
||
|
||
# 安装Python依赖
|
||
if [ -f "${SCRIPT_DIR}/requirements.txt" ]; then
|
||
echo "正在安装Python依赖包..."
|
||
cd ${SCRIPT_DIR}
|
||
if ${PIP_CMD} install -r requirements.txt; then
|
||
echo -e "${GREEN}✅${NC} Python依赖包安装成功"
|
||
else
|
||
echo -e "${RED}❌${NC} Python依赖包安装失败"
|
||
exit 1
|
||
fi
|
||
else
|
||
echo -e "${YELLOW}警告: requirements.txt 文件不存在${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查monitor.py是否存在
|
||
if [ ! -f "${SCRIPT_DIR}/monitor.py" ]; then
|
||
echo -e "${RED}错误: monitor.py 文件不存在${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# 创建日志目录
|
||
LOG_DIR="${SCRIPT_DIR}/logs"
|
||
mkdir -p ${LOG_DIR}
|
||
chmod 755 ${LOG_DIR}
|
||
|
||
echo ""
|
||
echo "正在创建systemd服务..."
|
||
|
||
# 创建systemd服务文件
|
||
cat > ${SERVICE_FILE} << EOF
|
||
[Unit]
|
||
Description=Heyun IDC VPS Monitor Service
|
||
After=network.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
WorkingDirectory=${SCRIPT_DIR}
|
||
ExecStart=${PYTHON_CMD} ${SCRIPT_DIR}/monitor.py
|
||
Restart=always
|
||
RestartSec=10
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
SyslogIdentifier=${SERVICE_NAME}
|
||
|
||
# 资源限制
|
||
LimitNOFILE=65536
|
||
|
||
# 安全设置
|
||
NoNewPrivileges=true
|
||
ProtectSystem=strict
|
||
ReadWritePaths=${SCRIPT_DIR}
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
# 重新加载systemd配置
|
||
systemctl daemon-reload
|
||
|
||
# 启用服务(开机自启)
|
||
systemctl enable ${SERVICE_NAME}
|
||
|
||
# 启动服务
|
||
echo ""
|
||
echo "正在启动服务..."
|
||
systemctl start ${SERVICE_NAME}
|
||
|
||
# 检查服务状态
|
||
sleep 2
|
||
if systemctl is-active --quiet ${SERVICE_NAME}; then
|
||
echo -e "${GREEN}✅${NC} ${SERVICE_NAME} 服务已成功安装并启动"
|
||
echo -e "${GREEN}✅${NC} 服务状态: 运行中"
|
||
else
|
||
echo -e "${RED}❌${NC} ${SERVICE_NAME} 服务启动失败"
|
||
echo ""
|
||
echo "请检查日志:"
|
||
echo " journalctl -u ${SERVICE_NAME} -n 50 --no-pager"
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo -e "${GREEN}安装完成!${NC}"
|
||
echo "=========================================="
|
||
echo ""
|
||
echo "常用命令:"
|
||
echo -e " ${YELLOW}查看服务状态:${NC} systemctl status ${SERVICE_NAME}"
|
||
echo -e " ${YELLOW}查看实时日志:${NC} journalctl -u ${SERVICE_NAME} -f"
|
||
echo -e " ${YELLOW}查看正常日志:${NC} tail -f ${LOG_DIR}/monitor.log"
|
||
echo -e " ${YELLOW}查看异常日志:${NC} tail -f ${LOG_DIR}/error.log"
|
||
echo -e " ${YELLOW}停止服务:${NC} systemctl stop ${SERVICE_NAME}"
|
||
echo -e " ${YELLOW}重启服务:${NC} systemctl restart ${SERVICE_NAME}"
|
||
echo -e " ${YELLOW}卸载服务:${NC} cd ${SCRIPT_DIR} && ./uninstall.sh"
|
||
echo ""
|
||
echo "配置文件位置: ${CONFIG_FILE}"
|
||
echo "日志文件位置: ${LOG_DIR}"
|
||
echo "" |