Python中如何通过tail -f监控文件变化并实时交给Python -c处理?
错误的命令:
tail -f case.log | python -c "import sys, json, time; print(json.load(sys.stdin)['type']);"
此命令想要的结果: tail -f 一个文件, awk 或其它命令取到 json, 通过管理交给 python 处理. python 解析 json 并打出需要的字段.
jq 命令可以解决这个问题,不过服务器太多,不好在每台服务上装这个命令。python 却是 linux 都带的,所以舍近求远,看有没其它的解决方法。
Python中如何通过tail -f监控文件变化并实时交给Python -c处理?
https://gist.github.com/antonchen/0a3c513e2b09b04e2c60b52f96ccb091
手写的不知道能不能跑,反正是这个思路
这个问题挺有意思,在Linux环境下想用tail -f和Python -c联动处理实时日志。直接管道传递是行不通的,因为tail -f会持续输出,而python -c执行完就退出了。
核心思路是让Python脚本自己来充当tail -f的角色,持续读取文件新增内容。用subprocess模块调用tail -f并捕获其标准输出流是最直接的办法。
给你一个即拿即用的代码示例:
import subprocess
import sys
def process_line(line):
"""在这里定义你的处理逻辑"""
# 示例:打印行并添加前缀
print(f"[处理]: {line}", end='')
# 你可以在这里进行任何字符串处理、匹配、写入数据库等操作
def tail_and_process(filename):
try:
# 启动tail -f进程
proc = subprocess.Popen(
['tail', '-f', filename],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1 # 行缓冲
)
print(f"开始监控文件: {filename}")
print("按 Ctrl+C 停止")
# 持续读取输出
for line in proc.stdout:
process_line(line)
except KeyboardInterrupt:
print("\n监控已停止")
except FileNotFoundError:
print(f"错误: 文件 '{filename}' 不存在或tail命令不可用")
except Exception as e:
print(f"发生错误: {e}")
finally:
if 'proc' in locals():
proc.terminate()
if __name__ == "__main__":
if len(sys.argv) != 2:
print("用法: python script.py <filename>")
sys.exit(1)
tail_and_process(sys.argv[1])
如果你想用一行命令搞定,可以这样封装:
python -c "
import subprocess, sys
with subprocess.Popen(['tail', '-f', sys.argv[1]], stdout=subprocess.PIPE, text=True) as proc:
for line in proc.stdout:
print(f'[处理]: {line}', end='')
" your_logfile.log
不过说实话,这种复杂逻辑还是写成独立的.py文件更清晰。上面那个脚本保存为log_monitor.py,然后直接python log_monitor.py /path/to/logfile就行。
简单说就是别指望python -c能持续运行,得用脚本来循环读取。
可行,我干过,现在还在跑,没 WAF 的服务器把 nginx 日志 tail 给 php 脚本
如果只是简单过滤 直接 awk 就好
复杂处理直接整个用 python 实现 tail -f 的功能就好
按行处理的话可以这样,配合 supervisord 可以做 service 用
#!/bin/bash
tail -qFn0 /var/log/sample.log | <br>while read line ; do
echo “$line”
#do whatever you want
done
用 tail -f 和 subprocess 实现过简单解析后推送到下游的脚本,稍微改改应该能满足楼主的需求
https://github.com/iyaozhen/filebeat.py
收下大佬的思路
我的场景,一行一个条日志,其中一小部分是一条 json, 所以会用 awk 或其它切成 json 再管道给后面,不写脚本是因为能一行命令解决的,我就没想写个脚本了。
赞
赞赞赞,可以实现我想要的<br>tail -qFn0 caselog.log | while read line ; do; python -c "import sys, json, time; print(json.loads('$line')['type']);"; done<br>
tail -f caselog.log | jq ‘.type’ 这样?
是的 jq 可以解决
是个好思路
这样处理过 apache 日志 =。=
没看懂 tail -qFn0 里的 n0 参数, 为什么要把 line num 设为 0 呢 这样不就一行都不会输出了吗
不要用 Python,直接正则解决。grep awk sed 都行。
在这个场景里除非 JSON 结构很复杂导致必须要解析,否则 Python 是最慢的一环。
同需求
man tail
…
-n number
The location is number lines.
…
n0 只显示命令执行后追加到文件中的内容
n100 显示执行命令时最后 100 行,并把命令执行后追加到文件内容显示出来
解释得不好,手动测试一下便知。这里有没有 n0 影响不大,舍弃命令执行前内容可便于观察。
正解
求大神 QQ


