本文目录导读:

在Shell脚本中监控文件句柄数主要有以下几种方法,我会提供完整的脚本示例:
监控当前进程的文件句柄数
#!/bin/bash
# 监控指定进程的文件句柄数
PROCESS_NAME="nginx" # 替换为你需要监控的进程名
PID=$(pgrep -f "$PROCESS_NAME" | head -1)
if [ -z "$PID" ]; then
echo "进程 $PROCESS_NAME 不存在"
exit 1
fi
# 方法1:通过 /proc 文件系统
FD_COUNT=$(ls -l /proc/$PID/fd/ 2>/dev/null | wc -l)
echo "进程 $PROCESS_NAME (PID: $PID) 当前文件句柄数: $FD_COUNT"
# 方法2:通过 lsof 命令
LSOF_COUNT=$(lsof -p $PID 2>/dev/null | wc -l)
echo "进程 $PROCESS_NAME (PID: $PID) 通过lsof统计的句柄数: $LSOF_COUNT"
# 方法3:读取 /proc/pid/fd 目录计数
FD_COUNT_V2=$(find /proc/$PID/fd -type l 2>/dev/null | wc -l)
echo "进程 $PROCESS_NAME (PID: $PID) 文件描述符数量: $FD_COUNT_V2"
监控系统全局的文件句柄数
#!/bin/bash
# 获取系统文件句柄信息
get_system_fd_info() {
echo "=== 系统文件句柄信息 ==="
# 已分配的句柄数
ALLOCATED=$(cat /proc/sys/fs/file-nr | awk '{print $1}')
echo "已分配的文件句柄数: $ALLOCATED"
# 未使用的句柄数
UNUSED=$(cat /proc/sys/fs/file-nr | awk '{print $2}')
echo "未使用的文件句柄数: $UNUSED"
# 最大文件句柄数
MAX_FD=$(cat /proc/sys/fs/file-max)
echo "系统最大文件句柄数: $MAX_FD"
# 使用率计算
if [ "$MAX_FD" -gt 0 ]; then
USED_PERCENT=$(echo "scale=2; $ALLOCATED * 100 / $MAX_FD" | bc)
echo "文件句柄使用率: ${USED_PERCENT}%"
fi
}
# 执行监控
get_system_fd_info
完整的监控脚本(带告警和日志)
#!/bin/bash
# ========== 配置区域 ==========
PROCESS_NAME="java" # 需要监控的进程名
ALERT_THRESHOLD=80 # 告警阈值(百分比)
CHECK_INTERVAL=60 # 检查间隔(秒)
LOG_FILE="/var/log/fd_monitor.log"
# ========== 日志函数 ==========
log_message() {
local LEVEL=$1
local MESSAGE=$2
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$LEVEL] $MESSAGE" | tee -a "$LOG_FILE"
}
# ========== 获取进程文件句柄数 ==========
get_process_fd_count() {
local process_name=$1
local pid=$(pgrep -f "$process_name" | head -1)
if [ -z "$pid" ]; then
log_message "WARN" "进程 $process_name 未运行"
return 1
fi
local fd_count=$(ls -l /proc/$pid/fd/ 2>/dev/null | wc -l)
if [ -z "$fd_count" ]; then
log_message "ERROR" "无法获取进程 $process_name (PID: $pid) 的文件句柄数"
return 1
fi
echo "$fd_count"
return 0
}
# ========== 监控系统文件句柄 ==========
monitor_system_fd() {
local allocated=$(cat /proc/sys/fs/file-nr 2>/dev/null | awk '{print $1}')
local max_fd=$(cat /proc/sys/fs/file-max 2>/dev/null)
if [ -n "$allocated" ] && [ -n "$max_fd" ] && [ "$max_fd" -gt 0 ]; then
local usage_percent=$(echo "scale=2; $allocated * 100 / $max_fd" | bc)
echo "系统状态 - 已分配: $allocated, 最大: $max_fd, 使用率: ${usage_percent}%"
# 检查告警阈值
if (( $(echo "$usage_percent > $ALERT_THRESHOLD" | bc -l) )); then
log_message "ALERT" "警告: 系统文件句柄使用率 ${usage_percent}% 超过阈值 ${ALERT_THRESHOLD}%"
return 2
fi
else
log_message "ERROR" "无法获取系统文件句柄信息"
return 1
fi
return 0
}
# ========== 主监控循环 ==========
monitor_loop() {
log_message "INFO" "文件句柄监控启动 - 进程: $PROCESS_NAME, 告警阈值: ${ALERT_THRESHOLD}%, 检查间隔: ${CHECK_INTERVAL}s"
while true; do
# 获取进程文件句柄数
local fd_count=$(get_process_fd_count "$PROCESS_NAME")
local return_code=$?
if [ $return_code -eq 0 ] && [ -n "$fd_count" ]; then
log_message "INFO" "进程 $PROCESS_NAME 文件句柄数: $fd_count"
fi
# 监控系统文件句柄
monitor_system_fd
local sys_status=$?
if [ $sys_status -eq 2 ]; then
# 触发告警时,可以添加额外的操作
log_message "INFO" "告警触发,准备执行恢复操作..."
# 这里可以添加清理操作或通知管理员
fi
# 等待下一次检查
sleep "$CHECK_INTERVAL"
done
}
# ========== 主程序 ==========
main() {
# 检查必要的命令
for cmd in bc pgrep; do
if ! command -v $cmd &> /dev/null; then
echo "错误: 需要安装 $cmd 命令"
exit 1
fi
done
# 创建日志目录
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null
# 启动监控循环
monitor_loop
}
# 运行主程序
main
单次检查脚本(适合crontab定时执行)
#!/bin/bash
# 单次检查脚本 - 适合crontab定时执行
# 用法: */5 * * * * /path/to/check_fd.sh
ALERT_EMAIL="admin@example.com"
THRESHOLD=90
# 检查系统文件句柄
ALLOCATED=$(cat /proc/sys/fs/file-nr | awk '{print $1}')
MAX_FD=$(cat /proc/sys/fs/file-max)
USED_PERCENT=$(echo "scale=2; $ALLOCATED * 100 / $MAX_FD" | bc)
echo "文件句柄使用率: ${USED_PERCENT}%"
# 告警检查
if (( $(echo "$USED_PERCENT > $THRESHOLD" | bc -l) )); then
echo "警告: 文件句柄使用率 ${USED_PERCENT}% 超出阈值 ${THRESHOLD}%" | \
mail -s "文件句柄告警 - $(hostname)" "$ALERT_EMAIL"
# 显示占用最多的进程
echo "占用文件句柄最多的进程:"
for pid in $(ls /proc/ | grep -E '^[0-9]+$' | head -20); do
fd_count=$(ls -l /proc/$pid/fd 2>/dev/null | wc -l)
if [ "$fd_count" -gt 0 ]; then
process_name=$(cat /proc/$pid/comm 2>/dev/null)
echo "PID: $pid, 名称: $process_name, 句柄数: $fd_count"
fi
done | sort -t: -k3 -n | tail -10
fi
使用注意事项
权限要求
# 普通用户只能查看自己的进程 # 查看所有进程需要root权限 sudo ./monitor_fd.sh
crontab定时任务配置
# 每5分钟检查一次 */5 * * * * /path/to/check_fd.sh # 每1小时记录一次 0 * * * * /path/to/record_fd.sh
这个监控脚本可以帮助你及时发现文件句柄泄漏问题,防止系统资源耗尽。