Linuxマシンにデバイスを接続したときにスクリプトを実行したい。たとえば、マウスでxinput
を実行するか、特定のドライブでbackupscriptを実行します。
私はこれについて多くの記事を見てきましたが、最近は here および here です。しかし、私はそれを機能させることができません。
以下は、少なくともある種の応答を得ようとするいくつかの簡単な例です。
/ etc/udev/rules.d/test.rules
#KERNEL=="sd*", ATTRS{vendor}=="*", ATTRS{model}=="*", ATTRS{serial}=="*", RUN+="/usr/local/bin/test.sh"
#KERNEL=="sd*", ACTION=="add", "SUBSYSTEM=="usb", ATTRS{model}=="My Book 1140 ", ATTRS{serial}=="0841752394756103457194857249", RUN+="/usr/local/bin/test.sh"
#ACTION=="add", "SUBSYSTEM=="usb", RUN+="/usr/local/bin/test.sh"
#KERNEL=="sd*", ACTION=={add}, RUN+="/usr/local/bin/test.sh"
KERNEL=="sd*", RUN+="/usr/local/bin/test.sh"
KERNEL=="*", RUN+="/usr/local/bin/test.sh"
/ usr/local/bin/test.sh
#!/usr/bin/env bash
echo touched >> /var/log/test.log
if [ "${ACTION}" = "add" ] && [ -f "${DEVICE}" ]
then
echo ${DEVICE} >> /var/log/test.log
fi
Rulesフォルダーはinotify
によって監視され、すぐにアクティブになります。キーボード、マウス、タブレット、メモリスティック、USBドライブを何度も接続し直しますが、何もしません。変更されたログファイルはありません。
さて、少なくとも何かが機能していることを知るための最も簡単な方法は何でしょうか?機能していないものから作業するよりも、機能しているものから作業する方が簡単です。
特定のデバイスでスクリプトを実行する場合は、ベンダーIDと製品IDを使用できます
/etc/udev/rules.d/test.rules
:
ATTRS{idVendor}=="152d", ATTRS{idProduct}=="2329", RUN+="/tmp/test.sh"
test.sh
:
#! /bin/sh
env >>/tmp/test.log
file "/sys${DEVPATH}" >>/tmp/test.log
if [ "${ACTION}" = add -a -d "/sys${DEVPATH}" ]; then
echo "add ${DEVPATH}" >>/tmp/test.log
fi
env
を使用すると、udevから設定されている環境を確認でき、file
を使用すると、ファイルタイプを検出できます。
デバイスの具体的な属性はlsusb
で見つけることができます
lsusb
与える
...
バス001デバイス016:ID 152d:2329 JMicron Technology Corp./JMicron USA Technology Corp. JM20329 SATA Bridge
...
これは直接あなたの質問についてではなく、あなたが何をしているのかについてです。 udevからバックアップスクリプトを開始すると、2つの主要な問題に直面します。
私のアドバイスは、名前付きパイプをリッスンするスクリプトをユーザーのホームに作成し、次のように非同期で開始することです。
#!/bin/bash
PIPE="/tmp/IomegaUsbPipe"
REMOTE_PATH="/path/to/mount/point"
LOCAL_PATH="/local/path/"
doSynchronization()
{
#your backup here
}
trap "rm -f $PIPE" EXIT
#If the pipe doesn't exists, create it
if [[ ! -p $PIPE ]]; then
mkfifo $PIPE
fi
#If the disk is already plugged on startup, do a syn
if [[ -e "$REMOTE_PATH" ]]
then
doSynchronization
fi
#Make the permanent loop to watch the usb connection
while true
do
if read line <$PIPE; then
#Test the message red from the fifo
if [[ "$line" == "connected" ]]
then
#The usb has been plugged, wait for disk to be mounted by KDE
while [[ ! -e "$REMOTE_PATH" ]]
do
sleep 1
done
doSynchronization
else
echo "Unhandled message frome fifo : [$line]"
fi
fi
done
echo "Reader exiting"
注:kdeで自動マウントを使用しているため、フォルダーが表示されるかどうかを確認します。/dev/sd *パラメータをufoルールからfifoに渡して、スクリプトに自分でマウントできます。 fifoで書くには、udevがシェルではなく、そのリダイレクトが機能しないことを忘れないでください。あなたのRUNは次のようになります:
RUN + = "/ bin/sh -c '/ bin/echo connected >>/tmp/IomegaUsbPipe'"
https://askubuntu.com/a/516336 に解決策を投稿しました。また、ここに解決策をコピーして貼り付けています。
Pythonスクリプトを使用して pyudev を使用して、バックグラウンドで実行したままにします。このスクリプトはudevイベントをリッスンし(したがって、非常に効率的です)、必要なコードを実行します。私の場合、 デバイスをセットアップするためにxinput
コマンドを実行します ( 最新バージョンへのリンク )。
次に、同じスクリプトの短いバージョンを示します。
#!/usr/bin/env python3
import pyudev
import subprocess
def main():
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='usb')
monitor.start()
for device in iter(monitor.poll, None):
# I can add more logic here, to run different scripts for different devices.
subprocess.call(['/home/foo/foobar.sh', '--foo', '--bar'])
if __name__ == '__main__':
main()
USBデバイスが挿入されているときに起動時にスクリプトを実行するには、以下のソリューションを使用します。
ペンドライブまたはその他のUSBストレージをフォーマットし、その際に名前を付けます。次に/etc/rc.local
行を追加ls -q /dev/disk/by-label > /home/pi/label.txt
label.txtという名前のtxtファイルを作成します(他の名前でもかまいません)
次に/etc/rc.localに別の2行を追加します。
if grep -q USB_drive_name /home/pi/label.txt; then
Sudo /home/pi/script.sh
これで、名前がUSB_drive_nameのペンドライブが挿入されるたびに、スクリプトが実行されます。
上記のいくつかの小さな変更により、システムが稼働しているときにソリューションを使用できます。