如果 dmesg/kern.log 中出现某些内容,如何自动运行脚本

如果 dmesg/kern.log 中出现某些内容,如何自动运行脚本

运行带有 WD15 Dock 的 Dell 5285。eth0 会定期停止传输数据(并且无线不会自动开始传输)。在 dmesg 或 kern.log 中

“r8152 2-4.2:1.0 enx106530b73c5e:Tx 状态 -71”

出现(r8152 是用于 Realtek Semiconductor Corp. RTL8153 千兆以太网适配器的模块 - enx106530b73c5e 是 eth0 连接重命名为的模块)。

以下操作将重置以太网连接:

#!/bin/bash
#reset Ethernet device by ID
set -euo pipefail
IFS=$'\n\t'

VENDOR="0bda"
PRODUCT="8153"

for DIR in $(find /sys/bus/usb/devices/ -maxdepth 1 -type l); do
  if [[ -f $DIR/idVendor && -f $DIR/idProduct &&
        $(cat $DIR/idVendor) == $VENDOR && $(cat $DIR/idProduct) == $PRODUCT ]]; then
    echo 0 > $DIR/authorized
    sleep 3
    echo 1 > $DIR/authorized
  fi
done

我如何自动检查(至少每分钟一次) dmesg 或 kern.log 中的该条目,并在存在的情况下运行该脚本?

我在 Kubuntu 19.04 上运行 KXStudio,低延迟内核(通用上也有同样的问题)。

答案1

/sys 使用情况

请注意,在 /sys 中查找设备的更简单的方法是询问 udev:

for DIR in $(udevadm trigger -v -n -s usb -a idVendor=0bda -a idProduct=8153)

for DIR in $(udevadm trigger -v -n -s usb -p ID_VENDOR_ID=0bda -p ID_MODEL_ID=8153)

定期行动

要执行定期操作,通常使用计划任务。如果您希望每分钟 grep dmesg 一次以查找您的消息,则只需添加每分钟运行一次的 cron 作业并 grep dmesg 以查找您的消息。

* * * * * if dmesg | tail -100 | grep -qs "r8152.*Tx status -71"; then /etc/kick-realtek.sh; fi

(五个星号是 crontab 格式的一部分,表示计划时间和日期。)

这种简单方法的一个问题是,它会对全部此类消息,甚至是上次重置之前记录的旧消息。您可以通过向 dmesg 写入标记行来避免这种情况(或者甚至可以使用现有内核消息(如“检测到 USB 设备”)作为标记):

#!/usr/bin/env bash

if dmesg | tail -100 | awk '/r8152.*Tx status -71/ {x=1} /KICKED/ {x=0} END {exit(!x)}'; then
    /etc/kick-realtek.sh;
    echo "KICKED" > /dev/kmsg;
fi

或者,您可以阅读并记住此类错误消息的最后时间戳,但相比之下这太复杂了。

实时监控

更好的选择是使用一个可以持续接收日志消息的程序,而不必进行定期检查。例如:

dmesg --follow | ...

journalctl --dmesg --lines=10000 --follow | ...

tail -n 10000 -f /var/log/kern.log | ...

无论使用哪一个,都将其输出导入到检查每个传入行的循环中。在后台运行生成的脚本,理想情况下,您甚至可以将其转变为系统服务(/etc/systemd/system/*.service):

#!/usr/bin/env bash

... | while read -r line; do
    if [[ $line == *r8152*Tx\ status\ -71* ]]; then
        /etc/kick-realtek.sh
    fi
done

(您可以使用if echo "$line" | grep -qs ...; then或类似的,没关系。)

最后,许多服务器系统已经有一个持续接收所有日志消息的程序,例如rsyslog或者系统日志工具(这些程序是 dmesg 首先被复制到 /var/log 的方式。)它们通常可以过滤日志消息并运行程序:

答案2

抱歉没有早点跟进。我意识到运行脚本来重置以太网连接是不够的。以太网设备有时会被重新编号。而且,偶尔,系统会显示多个基座。

我认为,最好在某个时候更换底座。可能使用可插拔 USB-C 三显示器底座。不过我可能仍然遇到同样的问题: https://plugable.com/2016/06/30/investigating-usb-c-problems-on-some-dell-xps-and-precision-laptops/

答案3

已经有一段时间了... :) 希望您的问题现在已经得到妥善解决。对于以后遇到此问题的人,这里有一个实时监控的想法!

将以下内容添加到/etc/crontab或使用crontab -e

*/1 * * * * /usr/bin/timeout 1m bash -c "dmesg -w | tail -f | grep -qsm 1 'r8152.*Tx status -71' && /root/yourscript.sh"

这是如何运作的?

Crontab 每分钟运行该命令。

timeout 1m运行 1 分钟后停止进程

bash -c执行包含在其中的查询"",允许我们将管道字符与timeout

dmesg -w打印 dmesg 历史记录跟随实时输出

tail -f遵循实时输入(跳过历史记录)

grep仅匹配我们感兴趣的内容,根据是否匹配返回成功或失败

grep -qsm 1匹配单个结果后立即返回,但不将任何内容打印到控制台,从而阻止 crontab 发送通知电子邮件

Miscellaneous:
-s, --no-messages         suppress error messages
Output control:
-m, --max-count=NUM       stop after NUM matches
-q, --quiet, --silent     suppress all normal output

&&仅当上一条命令成功返回时才执行以下命令

/root/yourscript.sh匹配时应运行的脚本的路径

相关内容