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