You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux虚拟机中Cron执行Python脚本发送Suricata日志邮件失败排查

问题:Cron执行Python邮件脚本无响应(命令行运行正常)

背景

我是Python/Linux新手,在Linux虚拟机上运行Suricata,希望通过Cron每天清晨自动执行Python脚本,将fast.log中的最新15条告警以邮件形式发送给自己。

已执行操作

1. 设置Cron任务生成日志文件

计划每天5点执行tail命令:

0  5    * * *   root    tail -n 200 /var/log/suricata/fast.log > daylogs.txt

2. 编写Python邮件脚本(latest.py)

import smtplib

smtpObj = smtplib.SMTP('smtp.gmail.com', 587)
smtpObj.ehlo()

smtpObj.starttls()

smtpObj.login('x', 'xx')

with open('/var/log/suricata/fast.log', 'r') as file:
        lines=file.readlines()

g = open('/var/log/suricata/daylogs.txt', 'w+')

#print(g)

for i in range(1, 15):
        g.write(lines[i*-1])

print(g)

g.close()

with open ('/var/log/suricata/daylogs.txt', 'r') as file:
        m = file.read()

#message = str(m)

#str.split(message)

print(m)

smtpObj.sendmail('x@gmail.com', 'x@gmail.com', 'Subject: IDS ALERTS\n\n'+m)

smtpObj.quit()

3. 设置执行脚本的Cron任务

30 5    * * *   root    /var/log/suricata/latest.py

4. 文件权限信息

-rw-r--r-- 1 root root     342706 Aug 30 19:22 fast.log
-rw-r--r-- 1 root root        612 Aug  9 17:52 latest.py

问题现象

命令行直接运行Python脚本可以正常收到邮件,但Cron执行后无任何效果。

Syslog日志信息

Aug 30 05:30:01 rupert-VirtualBox CRON[1188615]: (CRON) info (No MTA installed, discarding output)
Aug 30 05:30:01 rupert-VirtualBox CRON[1188617]: (rupert) CMD (root    /var/log/suricata/latest.py)
Aug 30 05:30:01 rupert-VirtualBox CRON[1188616]: (CRON) info (No MTA installed, discarding output)
Aug 30 05:30:01 rupert-VirtualBox CRON[1188619]: (root) CMD (   /var/log/suricata/latest.py)
Aug 30 05:30:01 rupert-VirtualBox CRON[1188614]: (CRON) info (No MTA installed, discarding output)
今早的syslogs:
Aug 31 05:00:01 rupert-VirtualBox CRON[1235735]: (root) CMD (tail -n 200 /var/log/suricata/fast.log > daylogs.txt )
Aug 31 05:00:01 rupert-VirtualBox CRON[1235736]: (rupert) CMD (root    tail -n 200 /var/log/suricata/fast.log > daylogs.txt)
Aug 31 05:00:01 rupert-VirtualBox CRON[1235734]: (CRON) info (No MTA installed, discarding output)
Aug 31 05:00:01 rupert-VirtualBox CRON[1235737]: (root) CMD (   tail -n 200 /var/log/suricata/fast.log > daylogs.txt)

Aug 31 05:17:01 rupert-VirtualBox CRON[1235751]: (root) CMD (   cd / && run-parts --report /etc/cron.hourly)
Aug 31 05:30:01 rupert-VirtualBox CRON[1235762]: (root) CMD (/var/log/suricata/latest.py)
Aug 31 05:30:01 rupert-VirtualBox CRON[1235760]: (CRON) info (No MTA installed, discarding output)
Aug 31 05:30:01 rupert-VirtualBox CRON[1235763]: (rupert) CMD (root    /var/log/suricata/latest.py 2>&1)
Aug 31 05:30:01 rupert-VirtualBox CRON[1235761]: (CRON) info (No MTA installed, discarding output)
Aug 31 05:30:01 rupert-VirtualBox CRON[1235764]: (root) CMD (   /var/log/suricata/latest.py)
Aug 31 05:30:01 rupert-VirtualBox CRON[1235759]: (CRON) info (No MTA installed, discarding output)

解决建议

1. 修复Cron任务格式与冗余问题

从日志能看到存在重复任务,且部分任务格式错误(比如普通用户任务里写了root)。清理冗余任务,保留正确格式的条目:

# 仅保留一个tail任务,指定完整输出路径
0 5 * * * root tail -n 200 /var/log/suricata/fast.log > /var/log/suricata/daylogs.txt
# 指定Python完整路径执行脚本(用`which python3`可获取实际路径)
30 5 * * * root /usr/bin/python3 /var/log/suricata/latest.py

2. 给Python脚本添加执行权限

当前脚本无执行权限,Cron直接调用可能失败:

chmod +x /var/log/suricata/latest.py

同时在脚本开头添加shebang行,指定解释器:

#!/usr/bin/python3
# 原脚本内容...

3. 捕获脚本执行日志

修改Cron任务,将脚本输出和错误重定向到日志文件,方便排查问题:

30 5 * * * root /usr/bin/python3 /var/log/suricata/latest.py >> /var/log/suricata/cron_script.log 2>&1

4. 检查Gmail SMTP认证

如果使用Gmail,需确保:

  • 若未开启两步验证,需开启「不太安全的应用访问」
  • 若开启了两步验证,需使用应用专用密码登录SMTP

5. 简化脚本逻辑(可选)

无需依赖tail生成的文件,直接读取最新15条日志:

#!/usr/bin/python3
import smtplib

# 获取最新15条告警
with open('/var/log/suricata/fast.log', 'r') as f:
    lines = f.readlines()
latest_alerts = ''.join(lines[-15:]) if len(lines)>=15 else ''.join(lines)

# 发送邮件并捕获错误
try:
    smtpObj = smtplib.SMTP('smtp.gmail.com', 587)
    smtpObj.ehlo()
    smtpObj.starttls()
    smtpObj.login('你的邮箱@gmail.com', '你的密码/应用密码')
    smtpObj.sendmail('你的邮箱@gmail.com', '你的邮箱@gmail.com', f'Subject: IDS ALERTS\n\n{latest_alerts}')
    smtpObj.quit()
except Exception as e:
    with open('/var/log/suricata/email_error.log', 'a') as err_f:
        err_f.write(f"发送失败: {str(e)}\n")

内容的提问来源于stack exchange,提问作者robreiner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:51:32