USB 장치가 연결되어 있을 때 쉘스크립트를 실행하는 방법

USB 장치가 연결되어 있을 때 쉘스크립트를 실행하는 방법

장치가 Linux 시스템에 연결될 때 스크립트를 실행하고 싶습니다. 예를 들어 xinput마우스로 실행하거나 드라이브에서 백업 스크립트를 실행합니다.

최근에 이에 관한 기사를 많이 읽었습니다.여기그리고여기. 그러나 나는 그것을 작동시킬 수 없습니다.

다음은 최소한 어떤 유형의 응답을 얻으려는 몇 가지 간단한 예입니다.

/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

규칙 폴더는 모니터링되며 inotify즉시 활성화되어야 합니다. 키보드, 마우스, 태블릿, 메모리 스틱, USB 드라이브를 계속 다시 연결하지만 아무 것도 연결하지 않습니다. 로그 파일을 건드리지 않았습니다.

이제 무언가가 작동하고 있는지 최소한 알 수 있는 가장 쉬운 방법은 무엇일까요? 효과가 없는 것보다 효과가 있는 것에서 작업하는 것이 더 쉽습니다.

답변1

특정 장치에서 스크립트를 실행하려면 공급업체 및 제품 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
    

를 사용하면 envudev에서 설정한 환경을 볼 수 있으며, 을 사용하면 file파일 유형을 검색할 수 있습니다.

장치의 특정 속성은 다음을 통해 확인할 수 있습니다.lsusb

lsusb

주어진

...
버스 001 장치 016: ID 152d: 2329 JMicron Technologies, Inc. / JMicron Technologies Americas, Inc. JM20329 SATA 브리지
...

답변2

이는 귀하의 문제와 관련이 없으며 귀하가 하고 있는 일과 관련이 있습니다. udev에서 백업 스크립트를 시작하면 두 가지 주요 문제에 직면하게 됩니다.

  1. 장치가 준비되어 마운트할 준비가 되기 전에 스크립트가 시작될 수 있습니다. /dev 노드를 사용하여 마운트하려면 KERNEL=="sd*" 조건을 유지해야 합니다.
  2. 게다가 스크립트를 실행하는 데 시간이 좀 걸리는 경우(백업 스크립트에서 쉽게 발생할 수 있는 현상) 스크립트는 시작 직후(약 5초) 종료됩니다.
  3. 많은 복잡한 사용자 권한 문제에 직면하게 됩니다.

내 제안은 명명된 파이프를 수신하고 다음과 같이 비동기적으로 시작하는 스크립트를 사용자 홈 디렉터리에 만드는 것입니다.

#!/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 exist, 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 read 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 from fifo : [$line]"
        fi
    fi
done
echo "Reader exiting"

참고: kde를 사용하여 자동 마운트하므로 폴더가 나타나는지 확인합니다. udev 규칙의 fifo에 /dev/sd* 매개변수를 전달하고 이를 스크립트에 직접 마운트할 수 있습니다. fifo에 쓰려면 udev가 쉘이 아니며 리디렉션이 작동하지 않는다는 점을 잊지 마십시오. 실행은 다음과 같아야 합니다.

RUN+="/bin/sh -c '/bin/echo 연결 >> /tmp/IomegaUsbPipe'"

답변3

해결 방법을 게시했습니다.https://askubuntu.com/a/516336여기에 솔루션을 복사하여 붙여넣기도 했습니다.

Python으로 스크립트를 작성했습니다.푸유데프저는 백그라운드에서 실행되도록 둡니다. 스크립트는 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()

답변4

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이라는 펜 드라이브를 삽입할 때마다 스크립트가 실행됩니다.

약간의 수정을 통해 시스템이 실행되는 동안 위의 솔루션을 사용할 수 있습니다.

관련 정보