Linux端口监控脚本

bash 复制代码
#!/bin/bash

# 端口监控脚本 
# 功能:监控多个端口,根据端口状态执行不同的启动脚本

# 监控间隔(秒)
CHECK_INTERVAL=300  # 5分钟

# 日志文件
LOG_FILE="./port_monitor.log"

# ========== 端口和脚本配置区域 ==========
# 在这里配置需要监控的端口和对应的启动脚本
# 格式: "端口号:启动脚本绝对路径"
PORT_SCRIPTS=(
    "8080:/home/user/scripts/start_web.sh"
    "3000:/home/user/scripts/start_api.sh" 
    "3306:/home/user/scripts/start_mysql.sh"
    "5432:/home/user/scripts/start_postgres.sh"
)
# ========== 配置结束 ==========

# 记录日志函数
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# 检查端口状态函数
check_port() {
    local port=$1
    
    # 方法1: 使用 netcat (如果可用)
    if command -v nc >/dev/null 2>&1; then
        if nc -z 127.0.0.1 "$port" >/dev/null 2>&1; then
            return 0  # 端口开放
        else
            return 1  # 端口关闭
        fi
    fi
    
    # 方法2: 使用 ss (如果可用)
    if command -v ss >/dev/null 2>&1; then
        if ss -tln | grep -q ":$port "; then
            return 0
        else
            return 1
        fi
    fi
    
    # 方法3: 使用 /proc/net/tcp
    local hex_port=$(printf '%04X' "$port")
    if grep -q ":$hex_port " /proc/net/tcp 2>/dev/null; then
        return 0
    else
        return 1
    fi
}

# 执行监控检查
monitor_ports() {
    log_message "=== 开始端口监控检查 ==="
    
    for port_script in "${PORT_SCRIPTS[@]}"; do
        # 解析端口和脚本
        IFS=':' read -r port script <<< "$port_script"
        
        log_message "检查端口: $port"
        
        if check_port "$port"; then
            log_message "✓ 端口 $port 状态正常"
        else
            log_message "✗ 端口 $port 异常 - 执行启动脚本: $script"
            
            # 检查脚本是否存在
            if [[ ! -f "$script" ]]; then
                log_message "错误: 脚本不存在: $script"
                continue
            fi
            
            # 检查脚本是否可执行
            if [[ ! -x "$script" ]]; then
                log_message "错误: 脚本不可执行: $script"
                continue
            fi
            
            # 执行启动脚本
            log_message "执行脚本: $script"
            if "$script" >> "$LOG_FILE" 2>&1; then
                log_message "脚本执行成功: $script"
            else
                log_message "脚本执行失败: $script (退出码: $?)"
            fi
        fi
    done
    
    log_message "=== 端口监控检查完成 ==="
}

# 显示当前配置
show_config() {
    log_message "当前监控配置:"
    for port_script in "${PORT_SCRIPTS[@]}"; do
        IFS=':' read -r port script <<< "$port_script"
        log_message "  端口 $port -> $script"
    done
}

# 主监控循环
start_monitor() {
    log_message "启动端口监控服务 (PID: $$)"
    log_message "监控间隔: ${CHECK_INTERVAL}秒"
    show_config
    
    # 保存PID到文件,便于管理
    echo $$ > /tmp/port_monitor.pid
    
    # 主循环
    while true; do
        monitor_ports
        log_message "等待 ${CHECK_INTERVAL} 秒后再次检查..."
        sleep "$CHECK_INTERVAL"
    done
}

# 停止监控
stop_monitor() {
    if [[ -f "/tmp/port_monitor.pid" ]]; then
        local pid=$(cat /tmp/port_monitor.pid)
        if kill -0 "$pid" 2>/dev/null; then
            kill "$pid"
            rm -f /tmp/port_monitor.pid
            log_message "端口监控服务已停止 (PID: $pid)"
        else
            rm -f /tmp/port_monitor.pid
            log_message "端口监控服务未运行"
        fi
    else
        log_message "端口监控服务未运行"
    fi
}

# 查看状态
check_status() {
    if [[ -f "/tmp/port_monitor.pid" ]]; then
        local pid=$(cat /tmp/port_monitor.pid)
        if kill -0 "$pid" 2>/dev/null; then
            log_message "端口监控服务运行中 (PID: $pid)"
            return 0
        else
            rm -f /tmp/port_monitor.pid
            log_message "端口监控服务未运行"
            return 1
        fi
    else
        log_message "端口监控服务未运行"
        return 1
    fi
}

# 单次检查
run_once() {
    log_message "执行单次端口检查"
    show_config
    monitor_ports
}

# 显示帮助
show_help() {
    cat << EOF
端口监控脚本 - 简化版

使用方法: $0 [命令]

命令:
    start     启动监控(后台运行)
    stop      停止监控
    status    查看监控状态
    once      执行一次监控检查
    help      显示帮助信息

配置说明:
    编辑脚本中的 PORT_SCRIPTS 数组来配置端口和脚本
    格式: "端口号:脚本路径"

示例:
    $0 start    # 启动监控
    $0 status   # 查看状态
    $0 stop     # 停止监控

日志文件: $LOG_FILE
EOF
}

# 脚本主入口
case "${1:-help}" in
    start)
        # 如果已经在运行,先停止
        if check_status >/dev/null 2>&1; then
            log_message "服务已在运行,先停止旧进程"
            stop_monitor
            sleep 2
        fi
        
        # 后台启动
        nohup "$0" daemon >> "$LOG_FILE" 2>&1 &
        log_message "端口监控服务已在后台启动 (PID: $!)"
        ;;
        
    daemon)
        # 守护进程模式
        start_monitor
        ;;
        
    stop)
        stop_monitor
        ;;
        
    status)
        check_status
        ;;
        
    once)
        run_once
        ;;
        
    help|--help|-h)
        show_help
        ;;
        
    *)
        echo "未知命令: $1"
        echo "使用: $0 help 查看帮助"
        exit 1
        ;;
esac

使用方法

1.修改脚本配置

编辑脚本中的 PORT_SCRIPTS 数组,设置你的端口和脚本

2.给监控脚本执行权限

bash 复制代码
chmod +x port_monitor.sh

3.启动监控

bash 复制代码
./port_monitor.sh start

4.查看状态

bash 复制代码
./port_monitor.sh status

5.停止监控

bash 复制代码
./port_monitor.sh stop

6.单次检查

bash 复制代码
./port_monitor.sh once

7.单次检查

bash 复制代码
tail -f ./port_monitor.log
相关推荐
Wang's Blog3 小时前
Linux小课堂: 深入理解前后台进程控制机制——基于 &、nohup、Ctrl+Z、bg 与 fg 的完整实践体系
linux·运维·服务器
秉承初心3 小时前
Linux中Expect脚本和Shell的脚本核心特点解析、以及比对分析和应用场景
linux·运维·服务器·sh·exp
脏脏a3 小时前
【Linux】Linux:sudo 白名单配置与 GCC/G++ 编译器使用指南
linux·运维·服务器
阿金要当大魔王~~3 小时前
uniapp 请求携带数据 \\接口传值 \\ map遍历数据
前端·javascript·uni-app
hey_ner4 小时前
页面PDF文件格式预览(不使用pdf.js)
前端·javascript
over6974 小时前
JavaScript恋爱物语:当代码学会送花,对象字面量也能当红娘!
javascript
码农阿豪4 小时前
一个浏览器多人用?Docker+Neko+cpolar实现跨网共享
运维·docker·容器
三小河4 小时前
封装 classNames:让 Tailwindcss 类名处理更优雅
前端·javascript
起这个名字4 小时前
ESLint 导入语句的分组排序
前端·javascript