web-dev-qa-db-ja.com

dmesg / kern.logに何かが表示された場合、スクリプトを自動的に実行するにはどうすればよいですか?

WD15ドックでDell5285を実行します。定期的に、eth0はデータの転送を停止します(そしてワイヤレスは自動的に転送を開始しません)。 dmesgまたはkern.logのいずれか

"r8152 2-4.2:1.0 enx106530b73c5e:送信ステータス-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を自動的に(少なくとも1分に1回)チェックし、存在する場合はスクリプトを実行するにはどうすればよいですか?

Kubuntu 19.04、低レイテンシカーネルでKXStudioを実行しています(ジェネリックでも同じ問題)。

3
eris discordia

/ 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)

定期的な行動

定期的なアクションを実行するには、通常cronを使用します。メッセージのdmesgを1分に1回grepする場合は、1分に1回実行され、メッセージのdmesgをgrepsするcronジョブを追加するだけです。

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

(5つのアスタリスクはcrontab形式の一部であり、スケジュールの日時を示します。)

この単純なアプローチの問題の1つは、最後のリセットの前にログに記録された古いメッセージであっても、allそのようなメッセージに反応することです。これを回避するには、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などを使用できますが、問題ありません。)

最後に、多くのサーバーシステムalready haveプログラムは、rsyslogsyslog-ngなどのすべてのログメッセージを継続的に受信します。 (これらのプログラムは、dmesgが最初に/ var/logにコピーされる方法です。)多くの場合、ログメッセージをフィルタリングして、プログラムを実行できます。

2
user1686

すぐにフォローアップしなくてすみません。スクリプトを実行してイーサネット接続をリセットするだけでは不十分であることに気付きました。イーサネットデバイスは、場合によっては番号が付け直されるようです。また、システムに複数のドックが表示される場合がありました。

ある時点でドックを交換する方が良いと思います。おそらくプラグ可能なUSB-Cトリプルディスプレイドッキングステーションを使用します。私はまだ同じ問題を抱えているかもしれませんが: https://plugable.com/2016/06/30/investigating-usb-c-problems-on-some-Dell-xps-and-precision-laptops/

0
eris discordia