0

当我的 3d 打印机用完灯丝时,它会暂停而不发送任何警报消息。我能找到的唯一条目是 journalctl 上的一条消息,如下所示: Jan 22 04:36:39 ultimakersystem-flipflop_wsgi.py[2884]: INF - root:80 - PrintJobStatus updated! 6e408dcf-9887, paused

当打印机暂停时,我绝对需要得到提醒,否则打印将被破坏。有没有办法以编程方式轮询/解析 journalctl,例如通过 bash 或 python 脚本,并根据需要发送电子邮件?

4

2 回答 2

1

可能有其他方法可以比轮询更优雅地做到这一点,但 FWIW:

  1. journalctl可以对其输出进行时间过滤;例如查看最近 30 分钟的活动:
journalctl --since "30 min ago" --until "now"
  1. cron可以在不同的时间间隔运行作业;journalctl例如,要每 30 分钟运行一次上述作业,请将这一行放入您的crontab
0,30 * * * * /bin/journalctl --since "30 min ago" --until "now"
  1. journalctl必须检查上面的输出是否与感兴趣的日志条目匹配。从您发布的错误消息中,我不确切知道哪些关键词会提示空灯丝箱,但我们现在假设它们是ultimakersystemand pausedawk提供了一种可扩展的方式来查找匹配的单词和短语:awk '/pattern1/ && /pattern2/'当两种模式出现在同一行journalctl输出中时匹配,因此将输出中的 apipe添加journalctlawk; 上面的cron作业修改如下:
0,30 * * * * /bin/journalctl --since "30 min ago" --until "now" | awk '/ultimakersystem/ && /paused/'
  1. 最后一步是测试是否awk找到匹配项,如果找到,则向指定用户发送消息。如果匹配到一个或多个,只需要发送一封电子邮件,因此将在一个END部分进行匹配测试。cron作业再次更新如下:
0,30 * * * * /bin/journalctl --since "30 min ago" --until "now" | awk '/ultimakersystem/ && /paused/ {m=1}; END { if (m == 1){system("cat warn.txt | mail -s FILAMENT_NEEDED $USER")} }'

awk使用模式-动作范式;/ultimakersystem/ && /paused/格局{m=1}行动awk处理完所有journalctl输出后,END执行该部分。一个简单的if (m == 1)测试确定是否发生了一个或多个匹配,如果是,mail则调用该命令来发送定义在warn.txt. GNUawksystem函数REF提供对系统命令库的访问。

在更改此配方的许多其他可能性中,可以通过替换为 将日期时间戳插入电子邮件正文,并将邮件发送给除. 请参阅或您的电子邮件客户端的文档。cat warn.txtdate$USERman mail

于 2022-01-31T06:37:14.023 回答
1

我已经用 python 脚本解决了这个问题。我认为它比 cronjob 更有效,因为它会在找到关键字(在本例中为“暂停”一词)时做出反应,而无需轮询。

import systemd.journal
import socket
from time import sleep
import smtplib
from smtplib import SMTP

def main():
  j = systemd.journal.Reader()
  j.seek_tail()
  j.get_previous()
  while True:
    event = j.wait(-1)
    if event == systemd.journal.APPEND:
      for entry in j:
         print (entry['MESSAGE'])
         alertmail(entry['MESSAGE'])

def alertmail(logEntry):
    # returns first occurrence of Substring
    trigger_text = 'pause'
    result = logEntry.find(trigger_text)
    if (logEntry.find(trigger_text) != -1):
        print ("Contains '" + trigger_text + "' at index:", result)

        fromaddr = "ultimaker@mymailstrasse.com"
        toaddrs  = "aag@bluewin.ch"
        msg = "ultimaker has paused!!! " + logEntry
        smtp = smtplib.SMTP('mail.mymailstrasse.com', port='587')
        smtp.ehlo()  # send the extended hello to our server
        smtp.starttls()  # tell server we want to communicate with TLS encryption
        smtp.login('ultimaker@mail.mymailstrasse.com', 'pw')  # login to our email server

        # send our email message 'msg' to our boss
        smtp.sendmail('ultimaker@mail.mymailstrasse.com',
                    'aag@bluewin.ch',
                    msg)
                    
        smtp.quit()  # finally, don't forget to close the connection
    else:
        print ("Doesn't contain given substring")

if __name__ == '__main__':
    main()
于 2022-01-31T10:08:44.783 回答