고쳐 쓰다

고쳐 쓰다

설치 후 USB에 폴더를 만들려고 합니다. **ID_FS_UUID_ENC** (64AC6F22AC6EEE4C)매개변수로 보내고 start.sh이 경로에 하위 폴더를 생성하는 다음 udev 규칙을 사용하고 있습니다 ./media/pi/64AC6F22AC6EEE4C

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"  
# Import FS infos  
IMPORT{program}="/sbin/blkid -o udev -p %N"
# Get a label if present, otherwise specify one  
#ENV{ID_FS_UUID_ENC}!="", ENV{dir_name}="%E{ID_FS_UUID_ENC}"  
#ENV{ID_FS_UUID_ENC}=="", ENV{dir_name}=""  
# Global mount options  
ACTION=="add", DRIVERS=="usb-storage", RUN+="/usr/bin/setsid /home/pi/raspberry-stilas/start.sh %E{ID_FS_UUID_ENC}"
ACTION=="add", DRIVERS=="usb-storage", RUN+="/bin/sh -c 'echo == >> /home/pi/raspberry-stilas/usb-storage-env.log; env >> /home/pi/raspberry-stilas/usb-storage-env.log'"
# Exit  
LABEL="media_by_label_auto_mount_end"

이제 문제는 USB를 연결하면 start.sh새 폴더가 생성되고 전달된 폴더의 이름이 변경된다는 것입니다. 그래서 64AC6F22AC6EEE4C새 폴더를 만들고 USB 라벨의 이름을 64AC6F22AC6EEE4C1. USB가 마운트되지 않은 상태에서 폴더를 생성하려고 하는 건가요?

고쳐 쓰다

시스템 로그와 커스텀 로그를 확인해 보니 스크립트가 실행된 후 디바이스가 설치되는 것 같습니다. 설치 후에만 실행할 수 있는 방법이 있나요?

Custom Log - Stilas Python program run at 2019-05-18 11:33:01 PM
Syslog - May 18 23:33:02 raspberrypi udisksd[725]: Mounted /dev/sda1 at /media/pi/64AC6F22AC6EEE4C1 on behalf of uid 1000

추가 후 로그인sleep 5

May 19 01:33:40 raspberrypi kernel: [  944.893519] usb 1-1.2: USB disconnect, device number 8
May 19 01:33:42 raspberrypi kernel: [  947.749507] usb 1-1.2: new high-speed USB device number 9 using dwc_otg
May 19 01:33:43 raspberrypi kernel: [  947.880955] usb 1-1.2: New USB device found, idVendor=0781, idProduct=558a
May 19 01:33:43 raspberrypi kernel: [  947.880971] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
May 19 01:33:43 raspberrypi kernel: [  947.880980] usb 1-1.2: Product: Ultra
May 19 01:33:43 raspberrypi kernel: [  947.880988] usb 1-1.2: Manufacturer: SanDisk
May 19 01:33:43 raspberrypi kernel: [  947.880997] usb 1-1.2: SerialNumber: 4C530001270213117013
May 19 01:33:43 raspberrypi kernel: [  947.881806] usb-storage 1-1.2:1.0: USB Mass Storage device detected
May 19 01:33:43 raspberrypi kernel: [  947.882227] scsi host1: usb-storage 1-1.2:1.0
May 19 01:33:43 raspberrypi mtp-probe: checking bus 1, device 9: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2"
May 19 01:33:43 raspberrypi mtp-probe: bus: 1, device: 9 was not an MTP device
May 19 01:33:44 raspberrypi kernel: [  948.890623] scsi 1:0:0:0: Direct-Access     SanDisk  Ultra            1.00 PQ: 0 ANSI: 6
May 19 01:33:44 raspberrypi kernel: [  948.891609] sd 1:0:0:0: Attached scsi generic sg1 type 0
May 19 01:33:44 raspberrypi kernel: [  948.891730] sd 1:0:0:0: [sdb] 120127488 512-byte logical blocks: (61.5 GB/57.3 GiB)
May 19 01:33:44 raspberrypi kernel: [  948.892813] sd 1:0:0:0: [sdb] Write Protect is off
May 19 01:33:44 raspberrypi kernel: [  948.892828] sd 1:0:0:0: [sdb] Mode Sense: 43 00 00 00
May 19 01:33:44 raspberrypi kernel: [  948.893398] sd 1:0:0:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
May 19 01:33:44 raspberrypi kernel: [  948.902832]  sdb: sdb1
May 19 01:33:44 raspberrypi kernel: [  948.905690] sd 1:0:0:0: [sdb] Attached SCSI removable disk

start.sh

#!/bin/sh
sleep 5
echo "Device Mounted on - `date +"%Y-%m-%d %r."` Path - /media/pi/{$1}" env >> /home/pi/raspberry-stilas/mount.log
if [ "$1" != "" ]; then
  echo "Stilas Python program run at `date +"%Y-%m-%d %r."` Path - /media/pi/{$1}" env >> /home/pi/raspberry-stilas/mount.log
  python3 /home/pi/raspberry-stilas/stilas/stilas.py "/media/pi/$1"
fi

답변1

라인 2 ( 라인 1) /home/pi/start.sh에 shebang이 있고 실행 비트( )가 설정되어 있다고 가정합니다 .#!/bin/shsleep 5chmod +x /home/pi/start.sh

을 사용하면 setsid포크됩니다. 이는 스크립트 실행이 백그라운드에서 실행된다는 의미입니다. 위의 절전 모드는 시스템에 USB 장치를 마운트할 시간을 제공하기 위한 것입니다. Udev는 장치를 마운트하기 전에 스크립트가 완료될 때까지 기다리지 않고 setsid즉시 반환되며 장치는 빠르게 마운트되어야 합니다.

ACTION=="add", DRIVERS=="usb-storage", RUN+="/usr/bin/setsid /home/pi/start.sh %E{ID_FS_UUID_ENC}"

편집: udev는 모든 하위 프로세스를 기다리므로 프로세스는 자체 그룹을 만들어야 합니다.

/home/pi/start.sh다음 헤더가 있는지 확인하세요 .

#!/bin/sh
pgid_from_pid() {
    local pid=$1
    ps -o pgid= "$pid" 2>/dev/null | egrep -o "[0-9]+"
}

pid="$$"
if [ "$pid" != "$(pgid_from_pid $pid)" ]; then
    exec setsid "$(readlink -f "$0")" "$@"
fi
sleep 5

init.sh 스크립트를 생성합니다:

#!/bin/sh
/home/pi/start.sh "$@"

우리는 다음 udev 규칙을 결합합니다:

ACTION=="add", DRIVERS=="usb-storage", RUN+="/bin/sh /home/pi/init.sh %E{ID_FS_UUID_ENC}"

답변2

최신 udev 시스템에서는 더 이상 작동하지 않는 답변을 포크하는 것이 좋습니다.

RUN
...
Starting daemons or other long running processes is not appropriate for
udev; the forked processes, detached or not, will be unconditionally killed
after the event handling has finished.

일반적인 systemd 서비스를 사용하여 mount장치를 설치할 수 있습니다. 다음을 사용할 수 있습니다. sudo systemctl list-units -t mount장치의 systemd 설치를 찾아 이름을 적습니다.

그런 다음 /etc/systemd/system/your.service "

[Unit] 
Description=My mount script trigger 
Requires=<whatever the command above returned>.mount 
After=<whatever the command above returned>.mount 

[Service] 
ExecStart=/home/pi/start.sh 

[Install] 
WantedBy=<whatever the command above returned>.mount 

이점: 설정이 용이함

결점: 특정 이름을 가진 USB 장치에만 적용됩니다. 스크립트에서 UUID를 직접 알아내야 합니다.

답변3

연결된 USB 플래시 드라이브(자율 BBB 장치에 연결됨)에 반응하는 무언가를 구현해야 합니다. 장치 이름을 가져오고, 거기에 파일 시스템을 마운트하고, 거기에 rsync 작업을 수행하고, 마운트 해제합니다.

동시성 문제(예: 병렬로 장치와 충돌하는 여러 문제), 적절한 오류 로깅 및 기타 시작 문제를 방지하기 위해 가장 확실한 방법은 스크립트를 시스템 원샷 서비스로 래핑하는 것입니다.

나에게 즉시 명확하지 않은 유일한 문제는 장치를 해당 서비스에 올바르게 전달하는 방법입니다.

Google 결과를 조사한 후(심지어 기사도 찾았음) 결국 현재 최선의 접근 방식인 것으로 보이는 "udev의 SYSTEMD_WANTS 및 systemd의 템플릿 유닛 페어링" 구문 분석 스레드를 찾았습니다.

내 상황에 맞게 조정하고 장치 인스턴스화 서비스의 일반 패턴과 결합하여 다음 구성을 얻었습니다.

udev 규칙:

ACTION=="add", PROGRAM="/usr/bin/systemd-escape -p [email protected] %E{ID_FS_UUID_ENC}", ENV{SYSTEMD_WANTS}+="%c"

[이메일 보호됨]:

[Unit]
BindTo=%i.device
After=%i.device

[Service]
Type=oneshot
TimeoutStartSec=300
ExecStart=/home/pi/raspberry-stilas/start.sh /%I

에서 적응여기.

관련 정보