udev와의 싸움

udev와의 싸움

automountUbuntu에서 SD 카드를 사용하고 싶습니다 . udevadm(or) 를 사용하여 다음 규칙을 시도 했습니다 /lib/systemd/systemd-udevd.

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_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"
# Global mount options
ACTION=="add|change", ENV{mount_options}="relatime"
# Filesystem-specific mount options
ACTION=="add|change", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"
# Mount the device
ACTION=="add|change", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}", RUN+=" echo /bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name\
} > /tmp/debug_out.txt"
#ACTION=="add|change"
# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"
# Exit
LABEL="media_by_label_auto_mount_end"

코드는 인터넷에서 나옵니다.

`udevadm monitor` indicates that the card is detected

KERNEL[1778159.935932] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
KERNEL[1778159.939553] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)
KERNEL[1778159.942501] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
KERNEL[1778159.942615] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)
UDEV  [1778160.026230] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
UDEV  [1778160.101285] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)
UDEV  [1778160.184648] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc (block)
KERNEL[1778160.320013] add      /kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(14341:systemd-udevd.service) (cgroup)
UDEV  [1778160.322555] add      /kernel/slab/ext4_inode_cache/cgroup/ext4_inode_cache(14341:systemd-udevd.service) (cgroup)
KERNEL[1778160.387280] add      /kernel/slab/fat_inode_cache/cgroup/fat_inode_cache(14341:systemd-udevd.service) (cgroup)
UDEV  [1778160.388849] add      /kernel/slab/fat_inode_cache/cgroup/fat_inode_cache(14341:systemd-udevd.service) (cgroup)
UDEV  [1778160.418509] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1 (block)

출력 udevadm test /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host11/target11:0:0/11:0:0:0/block/sdc/sdc1도 좋아 보이는데

[...]
run: '/bin/mkdir -p /media/usbhd-sdc1'
run: '/bin/mount -o relatime /dev/sdc1 /media/usbhd-sdc1'
run: '/usr/bin/unshare -m /usr/bin/snap auto-import --mount=/dev/sdc1'
[...]

그러나 규칙은 디렉터리를 생성하기만 하고 카드를 탑재하지는 않습니다. 권한을 사용하여 위 규칙을 수동으로 실행하면 sudo예상대로 작동합니다(디렉토리 생성이 작동하지 않으므로 sudo문제가 되지 않음).

(추가 질문: 카드에서 파일을 복사하고 작업과 unmount카드를 트리거하고 싶습니다. 카드에서도 이 작업을 수행할 수 있습니까 unmount? 아니면 다른 메커니즘을 사용할 수 있습니까?)

=======================

아래 설명대로 모든 것을 변경했습니다.

Udev/rules.d

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"

ACTION=="add", SUBSYSTEM=="block",TAG+="systemd", ENV{SYSTEMD_WANTS}=sd-automounter@%k.service
ACTION=="change", SUBSYSTEM=="block",TAG+="systemd", RUN+="systemctl start sd-automounter@%k"
# Clean up after removal  
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"  
# Exit  

서비스 설명

# /etc/systemd/system/[email protected]
[Service]
Type=oneshot
ExecStart=/usr/local/libexec/sd-automounter %I(base)

그리고 서비스

#!/bin/sh
# /usr/local/libexec/sd-automounter
echo "" > /tmp/debug.out
DEVICE_NAME=/dev/"$1"
echo $DEVICE_NAME >>/tmp/debug.out
udevadm info --query=property --export $DEVICE_NAME >> /tmp/debug.out
echo "" >> /tmp/debug.out
CARD_NAME=$(udevadm info --query=property --export $DEVICE_NAME | grep ID_FS_LABEL= | awk -F\' '{print $2}')
echo $CARD_NAME >> /tmp/debug.out
#CARD_NAME=$(/sbin/blkid  | grep "$DEVICE_NAME" | awk -F\" '{print $2}' |sed 's/ /_/g')
udevadm info --query=property --export /dev/sdc1
echo $CARD_NAME
mkdir -p /media/$CARD_NAME
mount -t vfat $DEVICE_NAME /media/$CARD_NAME
thanks for all help in advance

수동으로 수행하면 systemctl start sd-automounter@sdd1매력처럼 작동합니다.

하지만 udevadm monitor표시하는 동안 제거하고 삽입하면 아무 일도 일어나지 않습니다

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[1977111.519970] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
KERNEL[1977111.523252] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)
KERNEL[1977111.526457] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
KERNEL[1977111.526572] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)
UDEV  [1977111.612257] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
UDEV  [1977111.614914] remove   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)
UDEV  [1977111.697870] change   /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd (block)
UDEV  [1977111.791344] add      /devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host12/target12:0:0/12:0:0:0/block/sdd/sdd1 (block)

답변1

systemd-udev 진짜더 이상 규칙에서 직접 파일 시스템을 마운트할 필요가 없습니다. 이 사이트에서 이에 대한 많은 질문을 찾을 수 있습니다 :-).

최신 버전의 systemd에서는 udev 서비스 파일에 SystemCallFilter=@system-service @module @raw-io. 파일 시스템을 마운트하는 데 필요한 시스템 호출이 허용되지 않습니다.

(그리고 만약 당신이한 번mountFUSE 파일 시스템 에 대해 직접 ntfs-3gFUSE 서버 프로세스를 시작하는 경우 이를 전용 시스템 장치(예: unit )에 두는 것이 가장 좋습니다 .mount. 현재 장치 내에 FUSE 프로세스를 유지하는 경우 FUSE 프로세스의 수명 주기는 실행 중인 장치의 수명 주기와 결합됩니다.

RUN+=규칙 의 명령과 관련된 향후(또는 현재) 문제를 방지하려면 대신 다음을 ENV{SYSTEMD_WANTS}=my-automounter@%k.service사용할 수 있습니다.

# /etc/systemd/system/[email protected]
[Service]
Type=oneshot
ExecStart=/usr/local/libexec/my-automounter %I
#!/bin/sh
# /usr/local/libexec/my-automounter

DEV=/dev/"$1"

# You can make this script as complicated as you want.
# You can read udev properties if you want, using 
# eval "$(udevadm info --query=property --export "$DEV")"
...

장치 호출을 수동으로 테스트하려면 를 사용할 수 있습니다 systemctl start my-automounter@sdc1.

systemd가 스크립트를 실행하는 동안 오류가 발생하면 systemctl status my-automounter@*또는 를 사용하여 오류 메시지를 볼 수 있습니다 journalctl -b -u my-automounter@*.

또한 udev특정 오류 보고서를 처리할 필요가 없습니다. 프로그램이 갑자기 멈출 경우를 대비해 두 가지 모두 유용한 오류 보고 기능이 sh있다고 생각합니다 . 예를 들어, :-) 로 차단된 시스템 호출을 호출하려고 했기 때문에 systemd프로그램이 신호에 의해 종료되었는지 보고해야 합니다 .SIGSYSSystemCallFilter=

답변2

두 번째 옵션의 문제점은 전체 경로를 사용해야 한다는 것입니다.

ACTION=="add", SUBSYSTEM=="block",TAG+="systemd", RUN+="/bin/systemctl start sd-automounter@%k"
ACTION=="change", SUBSYSTEM=="block",TAG+="systemd", RUN+="/bin/systemctl start sd-automounter@%k"

실행 옵션을 사용하여 추가하십시오.

관련 정보