如何限制SNMP Trap触发的Bash脚本执行次数以避免CPU峰值?
用FIFO队列控制SNMP Trap触发脚本的串行执行
核心思路是借助**命名管道(FIFO)**实现任务队列:所有SNMP Trap触发的请求都先写入队列,由一个常驻的守护进程从队列中逐个读取任务,串行执行目标脚本,彻底避免多脚本并发导致的CPU峰值。
具体实现步骤
创建命名管道
在系统中创建专门的队列文件,命名管道是内核级的队列机制,天然适配这类场景:mkfifo /var/tmp/snmp_trap_queue chmod 600 /var/tmp/snmp_trap_queue # 限制权限,避免无关进程写入编写守护进程脚本
写一个常驻脚本,负责从队列读取任务并串行执行目标脚本(示例命名为snmp_trap_daemon.sh):#!/bin/bash QUEUE="/var/tmp/snmp_trap_queue" TARGET_SCRIPT="/path/to/your/actual_processing_script.sh" LOG_FILE="/var/log/snmp_trap_execution.log" # 确保队列存在,防止意外删除 [ ! -p "$QUEUE" ] && mkfifo "$QUEUE" # 循环读取队列任务,串行执行 while read -r trap_args < "$QUEUE"; do echo "[$(date '+%Y-%m-%d %H:%M:%S')] Executing script with args: $trap_args" >> "$LOG_FILE" # 执行目标脚本并记录输出 "$TARGET_SCRIPT" $trap_args >> "$LOG_FILE" 2>&1 echo "[$(date '+%Y-%m-%d %H:%M:%S')] Script execution completed" >> "$LOG_FILE" done给脚本添加执行权限:
chmod +x /path/to/snmp_trap_daemon.sh修改原SNMP Trap触发脚本
把原来直接执行目标脚本的逻辑,改成将Trap参数写入队列:#!/bin/bash QUEUE="/var/tmp/snmp_trap_queue" # 将当前Trap的所有参数写入队列($@保留参数分隔符) echo "$@" > "$QUEUE"注:如果Trap数据包含特殊字符或换行,改用
printf "%q " "$@" > "$QUEUE"可保证参数传递的安全性。配置守护进程开机自启
用systemd管理守护进程,确保系统重启后自动运行:
创建/etc/systemd/system/snmp_trap_daemon.service文件:[Unit] Description=SNMP Trap Script Queue Daemon After=network.target snmpd.target # 依赖snmp服务,按需调整 [Service] User=root # 根据实际运行脚本的用户修改 ExecStart=/path/to/snmp_trap_daemon.sh Restart=always # 进程意外退出时自动重启 [Install] WantedBy=multi-user.target启用并启动服务:
systemctl daemon-reload systemctl enable --now snmp_trap_daemon.service
额外优化建议
- 写入超时处理:如果队列满了(守护进程处理过慢),写入进程可能挂起,可添加超时限制:
timeout 3s echo "$@" > "$QUEUE" || echo "[$(date)] Failed to write to queue (timeout)" >> /var/log/snmp_trap_errors.log - 队列监控:用
lsof /var/tmp/snmp_trap_queue查看读写进程,或在守护进程中维护计数,监控任务堆积情况。
内容的提问来源于stack exchange,提问作者Miguel7799
相关产品推荐
相关产品推荐

