web-dev-qa-db-ja.com

systemdがバージョン239に更新された後、メディアデバイスを自動マウントするUdevルールが機能しなくなりました

しばらくの間、メディアデバイスを自動マウントするためのudevルールが機能していました。

/ etc/udev/rules.d/61-mount_media_by_label.rules

#
# To propagate udev's mountpoint to the user space, MountFlags must have a value "shared" in the /usr/lib/systemd/system/systemd-udevd.service.
#

# Ignore devices that aren't storage block-devices and block-devices that are already listed in /etc/fstab.
KERNEL!="sd[a-z][1-9]*", GOTO="mount_media_by_label_end"
PROGRAM="/bin/grep -e '^UUID=%E{ID_FS_UUID}' /etc/fstab", RESULT!="", GOTO="mount_media_by_label_end"

# Decide the name for device's mountpoint directory, based on device's label.
ENV{ID_FS_LABEL}!="", ENV{mountpoint}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{mountpoint}="usb-%k"

# If device is being plugged in, set options for mount command.
ACTION=="add", ENV{mount_options}="relatime"
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="%E{mount_options},utf8,gid=100,umask=002"

# If device is being plugged in, create mountpoint directory in /media and mount device node to it.
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{mountpoint}", RUN+="/bin/mount -o %E{mount_options} /dev/%k /media/%E{mountpoint}"

# If device is being plugged out, unmount it and delete its mountpoint directory.
ACTION=="remove", ENV{mountpoint}!="", RUN+="/bin/umount -l /media/%E{mountpoint}", RUN+="/bin/rmdir /media/%E{mountpoint}"

# Label for early exit.
LABEL="mount_media_by_label_end"

このルールを機能させるには、MountFlagsオプションの値をsharedに変更するだけで
/ usr/lib/systemd/system/systemd-udevd.service
systemdをバージョン239に更新した後、このファイルは異なって見えます。
問題があるかもしれない2つの変更に気づきました:

  1. MountFlagsオプションはデフォルト設定では指定されていません。
  2. PrivateMountsに設定された新しいオプションyesがあります。

systemd's documentation から、PrivateMounts=noを設定するだけで、マウントポイントの伝播がユーザースペースに到達することがわかりました。

ただし、これは当てはまりません。
私が試してみました

  1. PrivateMounts=noの変更
  2. PrivateMounts=noを変更してMountFlags=sharedを追加する

しかし、どちらも機能しません。

systemd v239以降のudevルールからメディアデバイスをマウントする正しい方法は何ですか?

2
Iskustvo

このアプローチは最適ではない可能性があります。たとえば、ntfs-3gを使用した書き込み可能なNTFSのマウントをサポートしている場合、udevを再起動するとntfs-3gプロセスが強制終了されます。

最新のセキュリティdoctrineは、デスクトップがallリムーバブルファイルシステムのマウントにFuseの使用を開始する必要があることを示唆していることに注意してください。 https: //lwn.net/Articles/755593/

別のsystemdユニットを起動(および停止?)する方法を考え出し、これを推奨されるアプローチとして記述できれば、Archユーザーにこのパターンの使用を提案し続ける特殊なドキュメントがあれば望ましいでしょう:-)。別のsystemdユニットを使用すると、udevサービスに適用される制限を回避できます。

たとえば、systemd-run --no-block --scope -- my mount command hereを使用してsystemdスコープユニットでコマンドを起動します。

残念ながら、ntfs-3gを含むユニットに識別可能な名前を付けたい場合、100%正しい方法が何であるかはすぐにはわかりません。その名前の古いユニットがまだ「アクティブ」として追跡されているが、プロセスが終了した直後の場合、サービスに開始を要求するだけでは何も起こりません。問題を無視したり、名前のランダムなサフィックスを生成したり、この一連のイベントを除外したりできますが、もっと良い方法があるかもしれません。

私はこれをFuseでテストしていませんが、これを行う方法はsystemd-mountコマンドだと思います。

スーパーユーザーの回答 は、udevルールの実行中にデバイスでsystemd-mountを使用すると、正しく機能しない可能性があることを示しています。これには、かなりバロック的な回避策が必要になります。 (RUN+="/path/to/my/script %k"を実行するsystemd-run --no-block --scope --unit=mount-$1 sh -c "systemctl start /dev/$1; systemd-mount ...")。

これを行う方法は次のようになると思います

ENV{SYSTEMD_WANTS}=my-mounter@%k.service

# /etc/systemd/system/[email protected]
[Service]
Type=oneshot
ExecStart=systemd-mount %I

#!/bin/sh
# /usr/local/lib/my-mounter
# You can make this as complicated as you want.
# (Although curiously systemd-mount also reads SYSTEMD_MOUNT_WHERE and
# SYSTEMD_MOUNT_OPTIONS properties if you set them on the udev device.)
# You could also read udev properties yourself using 
# eval "$(udevadm info --query=property --export)"

DEVNAME="$1"
systemd-mount "/dev/$DEVNAME"

systemd-mountのデフォルトでは、ファイルシステムは削除時に自動的にアンマウントされますが、後で自動的に作成されたマウントポイントディレクトリはクリーンアップされません(!)。


v239では2つの別々の変更 -2つの別々のディレクティブがあり、古い動作を取得するには元に戻す必要があります。

  1. PrivateMounts=yes。これをPrivateMounts=noに置き換えます。
  2. SystemCallFilter=@system-service @module @raw-io

    このディレクティブの使用はv239の新機能です。したがって、以前の動作を取り戻す最も簡単な方法は、それを完全に削除することです。

1
sourcejedi