Linux中如何监控文件变化并将新行通过WGET发送?
监控日志文件并发送匹配行的解决方案
问题定位
你的单行命令存在几个关键问题:
- 冗余的
xargs调用:已经通过read获取到每行内容,无需再用xargs处理,这会导致参数传递异常 tail -n 1会读取文件最后一行并发送,而非仅监控新增行,容易引发重复发送- 未对行内容做URL编码:包含
&、=、空格等特殊字符的行,会破坏POST数据格式 - Systemd服务环境下,未正确处理进程的标准输入输出,导致残留进程和重复执行
修复后的单行命令
直接去掉xargs,改用IFS= read -r确保完整读取行内容,并添加URL编码处理:
tail -f -n 0 /myLog.txt | grep --line-buffered 'info_im_looking_for' | while IFS= read -r line; do encoded_line=$(printf '%s' "$line" | sed 's/&/\&/g; s/=/\=/g; s/ /+/g; s/"/\"/g; s/'\''/\'/g') wget -q --delete-after --post-data "line=$encoded_line" "https://www.example.com/HelloWorld" done
-n 0:仅监控文件新增内容,避免读取历史行IFS= read -r:防止行首/行尾空格丢失,避免特殊字符被解析- URL编码:处理POST数据中的特殊字符,保证参数传递正确
Shell脚本实现(推荐)
单行命令不易维护,写成脚本更便于调试和扩展:
#!/bin/bash # 配置参数 LOG_FILE="/myLog.txt" TARGET_URL="https://www.example.com/HelloWorld" MATCH_PATTERN="info_im_looking_for" # 监控日志并发送匹配行 tail -f -n 0 "$LOG_FILE" | grep --line-buffered "$MATCH_PATTERN" | while IFS= read -r line; do # URL编码处理特殊字符 encoded_line=$(printf '%s' "$line" | sed 's/&/\&/g; s/=/\=/g; s/ /+/g; s/"/\"/g; s/'\''/\'/g') # 发送POST请求 wget -q --delete-after --post-data "line=$encoded_line" "$TARGET_URL" done
给脚本添加执行权限:
chmod +x /path/to/log-monitor.sh
Systemd服务配置
将脚本转为Systemd服务,解决残留进程和重复发送问题:
- 创建服务文件
/etc/systemd/system/log-monitor.service:
[Unit] Description=Monitor /myLog.txt and send matching lines to target URL After=network.target [Service] Type=simple ExecStart=/path/to/log-monitor.sh Restart=on-failure User=nobody Group=nogroup StandardOutput=null StandardError=journal+console [Install] WantedBy=multi-user.target
- 启用并启动服务:
systemctl daemon-reload systemctl enable --now log-monitor.service
Type=simple:告诉Systemd进程启动后会持续运行Restart=on-failure:进程意外退出时自动重启User=nobody:以低权限用户运行,提升安全性StandardOutput=null:避免日志输出堆积,异常信息通过journalctl -u log-monitor.service查看
内容的提问来源于stack exchange,提问作者Michael Cropper
相关产品推荐
相关产品推荐

