udisks

来自 ArchWiki

udisks 提供一个守护进程 udisksd,它实现了用于查询和操作存储设备的 D-Bus 接口,以及一个命令行工具 udisksctl,用于查询和使用该守护进程。

安装

安装 udisks2 软件包。

udisksd(8)D-Bus 按需启动,不应显式启用。它可以通过命令行 udisksctl(1) 进行控制。

配置

权限

用户可以使用 udisks 执行的操作受 polkit 限制。如果 用户会话 未激活或不存在(例如,从 systemd/User 服务控制 udisks 时),请相应地调整 polkit 规则。

请参阅 https://github.com/coldfix/udiskie/wiki/Permissions 以了解 storage 组的常见 udisks 权限,以及 [1] 以了解更严格的示例。如果您正在使用 Dolphin,您可能会看到 [2]

默认挂载选项

可以在 /etc/udisks2/mount_options.conf 中定义默认挂载选项。如果该文件尚不存在,请创建它。内置默认值和一些示例可以在 /etc/udisks2/mount_options.conf.example 中看到。[3]

这些选项可以针对特定的文件系统类型。例如,使用启用 zstd 压缩挂载 btrfs 文件系统

/etc/udisks2/mount_options.conf
[defaults]
btrfs_defaults=compress=zstd
注意: 行会覆盖相应的内置默认值。请确保不要以这种方式意外删除挂载选项。

用法

要手动挂载可移动驱动器,例如 /dev/sdc

$ udisksctl mount -b /dev/sdc1

要卸载

$ udisksctl unmount -b /dev/sdc1

更多信息请参考 udisksctl help

技巧与提示

挂载助手

设备的自动挂载很容易通过 udisks 包装器实现。另请参阅 应用程序列表/实用程序#挂载工具

注意: 桌面环境,例如 GNOMEPlasma 也可能提供 udisks 包装器。
  • bashmount — 一个 bash 脚本,用于以普通用户身份挂载和管理可移动媒体。
https://github.com/jamielinux/bashmount || bashmountAUR
  • udiskie — 自动挂载器,具有可选的通知、托盘图标以及对密码保护的 LUKS 设备的支持。有关详细信息,请参阅 udiskie wiki
https://github.com/coldfix/udiskie || udiskie
  • udiskie-dmenuudiskie 的 dmenu 界面。
https://github.com/fogine/udiskie-dmenu || udiskie-dmenu-gitAUR
  • udisksvm — 用 Python3 编写并使用 Qt5 框架的 GUI 包装器。它使用鼠标点击来挂载、卸载可移动设备或弹出 CD/DVD。有关详细信息,请参阅 README 文件。
https://github.com/berbae/udisksvm || udisksvmAUR
https://github.com/IgnorantGuru/udevil || udevilAUR
注意: devmon 仅在 udevilpmount 缺少 SUID 权限时才使用 udisks2 进行挂载(按此顺序)。要删除此权限,请以 root 身份运行 chmod -s /usr/bin/udevil

udevadm monitor

您可以使用 udevadm monitor 监视块设备事件,并在创建新的块设备时挂载驱动器。过时的挂载点由 udisksd 自动删除,因此删除时不需要特殊操作。

#!/bin/sh

pathtoname() {
    udevadm info -p /sys/"$1" | awk -v FS== '/DEVNAME/ {print $2}'
}

stdbuf -oL -- udevadm monitor --udev -s block | while read -r -- _ _ event devpath _; do
        if [ "$event" = add ]; then
            devname=$(pathtoname "$devpath")
            udisksctl mount --block-device "$devname" --no-user-interaction
        fi
done

挂载到 /media

默认情况下,udisks2 将可移动驱动器挂载到 ACL 控制的目录 /run/media/$USER/ 下。如果您希望挂载到 /media,请使用此规则

/etc/udev/rules.d/99-udisks2.rules
# UDISKS_FILESYSTEM_SHARED
# ==1: mount filesystem to a shared directory (/media/VolumeName)
# ==0: mount filesystem to a private directory (/run/media/$USER/VolumeName)
# See udisks(8)
ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{UDISKS_FILESYSTEM_SHARED}="1"

由于 /media/run 不同,默认情况下未作为 tmpfs 挂载,您可能还希望创建一个 tmpfiles.d 代码片段,以便在每次启动时清理过时的挂载点

/etc/tmpfiles.d/media.conf
D /media 0755 root root 0 -

挂载循环设备

要轻松挂载 ISO 镜像,请使用以下命令

$ udisksctl loop-setup -r -f image.iso

这将创建一个只读循环设备,并显示准备挂载的 ISO 镜像。删除 -r 标志即可对其进行写入。上面 loop-setup 命令会输出创建的循环设备的名称。

只要特定的循环设备就位,您就可以卸载和重新挂载该镜像。完成特定循环设备的工作后,请使用

$ udisksctl loop-delete -b /dev/loop0

删除它。将 /dev/loop0 替换为特定循环设备的名称。

循环设备很廉价。因此,在实践中可以创建许多循环设备,而无需担心拒绝服务问题。请参阅 [4]

隐藏选定的分区

如果您希望阻止某些分区或驱动器显示在桌面上,您可以创建一个 udev 规则,例如 /etc/udev/rules.d/10-local.rules

KERNEL=="sda1", ENV{UDISKS_IGNORE}="1"
KERNEL=="sda2", ENV{UDISKS_IGNORE}="1"

显示除桌面上的 sda1sda2 之外的所有分区。

由于块设备名称在重新启动之间可能会更改,因此也可以使用 UUID 来隐藏分区或整个设备。仅在处理完 /usr/lib/udev/rules.d/60-persistent-storage.rules 后才能通过 UUID 进行匹配,因此请确保选择的文件名排序在其之后。例如

/etc/udev/rules.d/61-hide-partitions.rules
SUBSYSTEM=="block", ENV{ID_FS_UUID}=="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX", ENV{UDISKS_IGNORE}="1"

上面这行代码也适用于隐藏多设备 btrfs 文件系统,因为来自单个 btrfs 文件系统的所有设备将在设备之间共享相同的 UUID,但每个单独的设备将具有不同的 SUB_UUID。

应用 ATA 设置

在启动时以及连接驱动器时,udisksd 将应用存储在文件 /etc/udisks2/IDENTIFIER.conf 中的配置,其中 IDENTIFIER 是驱动器的 Drive:Id 属性的值。目前支持 ATA 设置。有关可用选项,请参阅 udisks(8)。这些设置的效果与 hdparm 的设置基本相同,但只要 udisks 守护程序自动启动,它们就是持久的。

例如,要将驱动器的待机超时设置为 240(20 分钟),请添加以下内容

/etc/udisks2/DriveId.conf
[ATA]
StandbyTimeout=240

要获取驱动器的 DriveId,请使用 udevadm info --query=all --name=sdx | grep ID_SERIAL | sed "s/_/-/g"

或者,使用 GUI 实用程序来管理配置文件,例如 gnome-disk-utility

故障排除

隐藏的设备

默认情况下,Udisks2 会向用户隐藏某些设备。如果不需要或存在其他问题,请将 /usr/lib/udev/rules.d/80-udisks2.rules 复制到 /etc/udev/rules.d/80-udisks2.rules,并删除副本中的以下部分

# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------
# Devices which should not be display in the user interface
[...]

损坏的待机定时器

udisks 守护程序定期轮询驱动器的 S.M.A.R.T. 数据。待机超时时间长于轮询间隔的硬盘驱动器可能无法进入待机状态。已经停止旋转的驱动器通常不受影响。到目前为止,似乎没有办法禁用轮询或更改 udisks2 的间隔。请参阅 [5], [6]

但是,udisks2 应用的待机超时似乎不受影响。要通过 udisks 设置待机超时,请参阅 #应用 ATA 设置

其他可能的解决方法可能是将超时时间设置为低于轮询间隔(10 分钟),或者使用 hdparm -y /dev/sdx 强制手动停止旋转。

NTFS 挂载失败

如果挂载 ntfs 分区失败并出现以下错误

Error mounting /dev/sdXY at [...]: wrong fs type, bad option, bad superblock on /dev/sdXY, missing codepage or helper program, or other error

并在以 root 身份运行的内核日志 journalctl/dmesg 中显示

ntfs: (device sdXY): parse_options(): Unrecognized mount option windows_names.

问题是(截至 udisks 2.10),默认使用 NTFS-3G 驱动程序,并且有两种解决方案

1:安装 NTFS-3G,然后重启机器。

此文章或章节的事实准确性存疑。

原因:/etc/udisks2/mount_options.conf.example 文件中所述,这些是内置的挂载选项(即默认值)。它们不需要显式设置。(在 Talk:Udisks#udisk2 with NTFS support 中讨论)

2:配置 udisks2。默认情况下,udisks2 未在 Arch 系统上配置,并且未为非本地文件系统定义任何默认值。最简单的方法是将 /etc/udisks2/mount.options.conf.example 复制到 /etc/udisks2/mount.options.conf 并取消注释以下行

/etc/udisks2/mount_options.conf
[defaults]
# 'ntfs' signature, the new 'ntfs3' kernel driver
ntfs:ntfs3_defaults=uid=$UID,gid=$GID
ntfs:ntfs3_allow=uid=$UID,gid=$GID,umask,dmask,fmask,iocharset,discard,nodiscard,sparse,nosparse,hidden,nohidden,sys_immutable,showmeta,noshowmeta,prealloc,noprealloc,hide_dot_files,nohide_dot_files,windows_names,nocase,case

并重启 udisk2 守护程序,或重启您的机器。

NTFS 文件创建失败(文件名相关)

udisks 2.8.2 通过将 windows_names 添加到 NTFS 挂载选项引入了破坏性更改,从而阻止创建与 Win32 不兼容的文件名,例如 nulscreenshot 23-08-21 19:22.jpg。 除此之外,这会导致 Steam Proton 停止初始化。要恢复此行为,请使用

/etc/udisks2/mount_options.conf
[defaults]
ntfs:ntfs_defaults=uid=$UID,gid=$GID

除非被访问,否则错误的文件名通常不会在 Windows 中引起问题。chkdsk 会将这些名称视为错误,并将重命名的文件移动到文件系统根目录下的 found.nnn 文件夹中。

在关机时自动关闭外部 HDD

如果外部 HDD 在系统关机时未正确断电,则可能需要修复此问题。

启用 udisks2.service

调用我们的脚本的服务可能如下所示

/etc/systemd/system/handle_external_hdds.service
[Unit]
Requires=udisks2.service
Requires=graphical.target
After=graphical.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStop=/usr/local/bin/handle_external_hdds.sh
[Install]
WantedBy=graphical.target

启用 handle_external_hdds.service

执行 systemd daemon-reload 以应用新设置。

重启或重启 graphical.target 以检查是否有效。

处理单个磁盘上任意数量的分区的示例脚本如下所示

/usr/local/bin/handle_external_hdds.sh
#!/bin/bash -u

declare -a uuids=(uuid_list)

# Only proceed if the drive is present.
if [[ ! -L "/dev/disk/by-uuid/${uuids[0]}" ]]; then
  exit 0
fi

for uuid in "${uuids[@]}"; do
  if findmnt "/dev/disk/by-uuid/$uuid"; then
    umount "/dev/disk/by-uuid/$uuid"
  fi
done

# udisksctl powers off proper drive even if its partition is supplied
udisksctl power-off -b "/dev/disk/by-uuid/${uuids[0]}"

uuid_list 是以空格分隔的 UUID 列表,对应于要检查的设备的分区,例如 "uuid_1" "uuid_2"

参见