为什么Systemd_wants不会从udev'evose''传递参数到服务文件。规则?

发布于 2025-01-28 04:42:18 字数 2070 浏览 5 评论 0原文

我正在尝试使用UDEV规则和SystemD来安装和卸载USB密钥。

我将解决方案基于此博客 env {systemd_wants}在“ add” udev规则中使用。我无法让env {systemd_wants}为“删除”规则工作,所以我最终使用了此博客条目从UDEV运行键运行SystemD Service文件。

尽管此解决方案可起作用 udev man page 说:“运行长时间的事件过程可能会阻止此或依赖设备的所有其他事件。”

这些是我使用的规则...

添加规则:

ACTION=="add", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \ 
ENV{DEVTYPE}=="partition", ENV{ENV_MOUNT_USB}="MOUNT", \ 
PROGRAM="/usr/bin/systemd-escape -p [email protected] \ 
$env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"

删除规则:

ACTION=="remove", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \ 
ENV{DEVTYPE}=="partition", RUN+="/bin/systemctl start usb-umount@%k.service"

这些是UDEV规则开始的SystemD服务文件。他们只是执行bash脚本以安装和安装USB密钥。

=“/cdn-cgi/l/email-potection” class =“ __ cf_email__” data-cfemail =“ 631610014E0C160D17234D1006111150AMAIL =”

[Unit]
Description=Mount USB Drive on %i
BindTo=%i.device
After=%i.device

[Service]
Type=oneshot
TimeoutStartSec=300
ExecStart=/usr/local/sbin/usb-mount.sh /%I

[Unit]
Description=UnMount USB Drive on %i

[Service]
Type=oneshot
TimeoutStartSec=300
ExecStart=/usr/local/sbin/usb-umount.sh /%I

> br> 但是,如果我在“删除”规则中使用env {system_wants},则独立USB密钥的设备块(例如: /dev /sdb1)不会传递给服务文件。实际上,我认为服务文件根本不运行。

我的问题
我的删除规则是否可以更改为与Env {System_wants}一起使用,而不是运行+= {..},以使 /dev /sdb1传递给服务文件,然后转到可以执行Un-Mount的脚本?

欢呼,

弯曲

I am trying to use udev rules and systemd to mount and unmount a USB key.

I am basing my solution below on an example from this blog where ENV{SYSTEMD_WANTS} is used in an "Add" udev rule. I could not get ENV{SYSTEMD_WANTS} to work for a "Remove" rule so I ended up using the example in this blog entry which runs a systemd service file from a udev RUN key.

Although this solution works the udev man page says: "Running an event process for a long period of time may block all further events for this or a dependent device."

These are the rules I use...

The Add Rule:

ACTION=="add", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \ 
ENV{DEVTYPE}=="partition", ENV{ENV_MOUNT_USB}="MOUNT", \ 
PROGRAM="/usr/bin/systemd-escape -p [email protected] \ 
$env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"

The Remove Rule:

ACTION=="remove", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \ 
ENV{DEVTYPE}=="partition", RUN+="/bin/systemctl start usb-umount@%k.service"

These are the systemd service files that the udev rules start. They simply execute bash scripts to mount and un-mount the USB key.

[email protected]

[Unit]
Description=Mount USB Drive on %i
BindTo=%i.device
After=%i.device

[Service]
Type=oneshot
TimeoutStartSec=300
ExecStart=/usr/local/sbin/usb-mount.sh /%I

[email protected]

[Unit]
Description=UnMount USB Drive on %i

[Service]
Type=oneshot
TimeoutStartSec=300
ExecStart=/usr/local/sbin/usb-umount.sh /%I

My Problem
But if I use ENV{SYSTEM_WANTS} in the "remove" rule the device block (e.g: /dev/sdb1) of the detaching USB key does NOT get passed to the service file. Actually I don't think the service file runs at all.

My Question
Can my remove rule be changed to work with ENV{SYSTEM_WANTS} and NOT RUN+={..} such that the /dev/sdb1 is passed to the service file and on to a script that can do the un-mount?

Cheers,

Flex

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丿*梦醉红颜 2025-02-04 04:42:18

经过大量调查,我对上面的问题有一个答案。

问题的说明

关键点在

•(在UDEV规则中)“ systemd_wants =” ...“添加类型的依赖项
WANT =从设备单元(例如:一个USB密钥)到指定单元
(即:一个系统服务单元)。”

•“ ... Systemd只能在wines =依赖项上行动
首先变得活跃。”

我通过插入和删除USB密钥进行了测试。通过测试此UDEV规则不起作用:

ACTION=="remove", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \
ENV{DEVTYPE}=="partition", ENV{SYSTEMD_WANTS}+="usb-umount@%k.service"

我会像这样进行调试:

sudo udevadm control --log-priority=debug
journalctl -f

当我删除已经插入的USB密钥时,我没有在Journal> Journal> Journal ctl调试输出中看到任何提及USB-Mount服务。因此,该服务文件甚至没有启动,这是因为人页面所述的内容(请参见上文)。

相比之下,当我将规则更改为此时:

ACTION=="remove", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \
ENV{DEVTYPE}=="partition", RUN+="/bin/systemctl start usb-umount@%k.service"

现在在Journal ctl输出中,我看到:

sdb1: Starting '/bin/systemctl start [email protected]'

关于为什么Systemd_wants在UDEV中不起作用的UDEV删除规则

从该reddit线程引用:

“ systemd_wants and systemd_user_wants对
动作==“删除”。看起来这些变量使Udev问
Systemd做某事,但这种关系实际上是另一个
四处走动:当变量是从systemd检索到UDEV的
设备单元正在添加到SystemD Manager。变量不是
在其他任何时候都可以检索。”

这也解释了为什么SystemD_Wants不会使UDEV“删除”规则运行的USB安装服务。

Reddit线程的新解决方案

还显示了使用UDEV“删除”操作的SystemD_Wants的回旋方式:

现在使用Udev响应从我的计算机上插入和插入的USB键,我只需要一个UDEV规则,灵感来自RedDit的启发post and 此博客/a>:

UDEV规则
•/etc/udev/rules.d/99-local.rules

ACTION=="add", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \
ENV{DEVTYPE}=="partition", ENV{ENV_MOUNT_USB}="USB-MOUNTED", \
PROGRAM="/usr/bin/systemd-escape -p [email protected] \ 
$env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"

服务文件
•/etc/systemd/system/

[Unit]
Description=Test-Mount USB Drive on %i
BindsTo=%i.device
After=%i.device

[Service]
Type=oneshot
RemainAfterExit=true
TimeoutStartSec=300
ExecStart=/usr/local/sbin/test-mount.sh /%I
ExecStop=/usr/local/sbin/test-umount.sh /%I

077736274732a6a66872697269734729747297462746275716e6464646462我使用的脚本...
•/USR/local/sbin/test-mount.sh

#!/bin/bash

#
# This script runs when a USB device is plugged in
#

DEVBASE=$1
DEVICE="${DEVBASE}"

# Create a Timestamp, e.g: 06.05.2022-20.11.49
current_time=$(date "+%d.%m.%Y-%H.%M.%S")

# Query the udev database which is available while the USB key is plugged in.
# However these udev properties are unavailable once the USB key is plugged out.
eval $(udevadm info --query=env --export $DEVICE)

# Create a temporary file
touch /tmp/test-mount.txt

# Add content to the file
echo ${current_time} > "/tmp/test-mount.txt"
echo ${DEVICE} >> "/tmp/test-mount.txt"
echo $ID_FS_LABEL  >> "/tmp/test-mount.txt"
echo $ENV_MOUNT_USB  >> "/tmp/test-mount.txt"

•/USR/Local/sbin/sbin/test-umount.sh

#!/bin/bash

#
# This script runs when a USB device is plugged out
#

DEVBASE=$1
DEVICE="${DEVBASE}"

# Create a Timestamp, e.g: 06.05.2022-20.11.49
current_time=$(date "+%d.%m.%Y-%H.%M.%S")

# Query the udev database which is available while the USB key is plugged in.
# However these udev properties are unavailable once the USB key is plugged out.
eval $(udevadm info --query=env --export $DEVICE)

# Create a temporary file
touch /tmp/test-umount.txt

# Add content to the file
echo ${current_time} > "/tmp/test-umount.txt"
echo ${DEVICE} >> "/tmp/test-umount.txt"
echo $ID_FS_LABEL  >> "/tmp/test-umount.txt"
echo $ENV_MOUNT_USB  >> "/tmp/test-umount.txt"
/usr/bin/printenv > /tmp/udev-env.txt

我用来测试和调试的命令
•插入USB并删除USB密钥:

ls -l /tmp

这样的调试...
•这确实是您要打扰测试UDEV规则的唯一方法!
•运行命令,然后插入并删除USB密钥。

sudo udevadm control --log-priority=debug
journalctl -f

还有这个...

udevadm monitor --subsystem-match=block --property --udev
udevadm monitor --property --udev

这样的测试...
•此测试不如上述测试,因为它仅模拟UDEV规则做!
•例如:对于 /dev /sdb1,您以下测试UDEV规则:

# sudo udevadm test --action=add /sys/class/block/sdb1

After much investigation I have an answer to my question above.

Explanation of Problem

The key points are in the Systemd device man page:

• (In a udev rule) "Systemd_wants="... "Adds dependencies of type
Wants= from the device unit (e.g: a USB Key) to the specified units
(i.e: a systemd service unit)."

• “...systemd will only act on Wants= dependencies when a device
first becomes active.”

I tested by inserting and removing a USB key. From testing this udev rule does not work:

ACTION=="remove", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \
ENV{DEVTYPE}=="partition", ENV{SYSTEMD_WANTS}+="usb-umount@%k.service"

I debugged like this:

sudo udevadm control --log-priority=debug
journalctl -f

When I removed the already inserted USB key I didn't see any mention of the usb-mount service in the journalctl debug output. So that service file doesn't even start which makes sense because of what the man page states (see above).

In contrast when I change the rule to this:

ACTION=="remove", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \
ENV{DEVTYPE}=="partition", RUN+="/bin/systemctl start usb-umount@%k.service"

Now in the journalctl output I see:

sdb1: Starting '/bin/systemctl start [email protected]'

There is a good discussion about why Systemd_Wants will not work in a udev remove rule in this Reddit thread.

To quote from that Reddit Thread:

“SYSTEMD_WANTS and SYSTEMD_USER_WANTS do not make sense with
ACTION=="remove". It may look like these variables make Udev ask
systemd to do something, but the relationship is actually the other
way around: the variable is retrieved from Udev by systemd when the
device unit is being added to the systemd manager. The variable is not
retrieved at any other time.”

This also explains why Systemd_Wants does not make the usb-mount service run from a udev "remove" rule.

A New solution

That Reddit Thread also shows a roundabout way to use systemd_wants with a udev “remove” action:

Now to use udev to respond to a USB key being plugged and unplugged from my machine I need just ONE udev rule, inspired by the Reddit post and this blog:

The udev rule
• /etc/udev/rules.d/99-local.rules

ACTION=="add", SUBSYSTEM=="block", ENV{ID_TYPE}="disk", \
ENV{DEVTYPE}=="partition", ENV{ENV_MOUNT_USB}="USB-MOUNTED", \
PROGRAM="/usr/bin/systemd-escape -p [email protected] \ 
$env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"

The Service file
• /etc/systemd/system/[email protected]

[Unit]
Description=Test-Mount USB Drive on %i
BindsTo=%i.device
After=%i.device

[Service]
Type=oneshot
RemainAfterExit=true
TimeoutStartSec=300
ExecStart=/usr/local/sbin/test-mount.sh /%I
ExecStop=/usr/local/sbin/test-umount.sh /%I

The scripts I used...
• /usr/local/sbin/test-mount.sh

#!/bin/bash

#
# This script runs when a USB device is plugged in
#

DEVBASE=$1
DEVICE="${DEVBASE}"

# Create a Timestamp, e.g: 06.05.2022-20.11.49
current_time=$(date "+%d.%m.%Y-%H.%M.%S")

# Query the udev database which is available while the USB key is plugged in.
# However these udev properties are unavailable once the USB key is plugged out.
eval $(udevadm info --query=env --export $DEVICE)

# Create a temporary file
touch /tmp/test-mount.txt

# Add content to the file
echo ${current_time} > "/tmp/test-mount.txt"
echo ${DEVICE} >> "/tmp/test-mount.txt"
echo $ID_FS_LABEL  >> "/tmp/test-mount.txt"
echo $ENV_MOUNT_USB  >> "/tmp/test-mount.txt"

• /usr/local/sbin/test-umount.sh

#!/bin/bash

#
# This script runs when a USB device is plugged out
#

DEVBASE=$1
DEVICE="${DEVBASE}"

# Create a Timestamp, e.g: 06.05.2022-20.11.49
current_time=$(date "+%d.%m.%Y-%H.%M.%S")

# Query the udev database which is available while the USB key is plugged in.
# However these udev properties are unavailable once the USB key is plugged out.
eval $(udevadm info --query=env --export $DEVICE)

# Create a temporary file
touch /tmp/test-umount.txt

# Add content to the file
echo ${current_time} > "/tmp/test-umount.txt"
echo ${DEVICE} >> "/tmp/test-umount.txt"
echo $ID_FS_LABEL  >> "/tmp/test-umount.txt"
echo $ENV_MOUNT_USB  >> "/tmp/test-umount.txt"
/usr/bin/printenv > /tmp/udev-env.txt

The commands I used to Test and Debug
• Insert USB and Remove USB key:

ls -l /tmp

Debug like this...
• This is really the only way you should bother testing a udev rule!
• Run the commands then insert and remove the USB key.

sudo udevadm control --log-priority=debug
journalctl -f

And also this...

udevadm monitor --subsystem-match=block --property --udev
udevadm monitor --property --udev

Test like this...
• This tests is not as useful as the above, as it only simulates what the udev rule would do!
• E.g: For /dev/sdb1 you test the udev rule like this:

# sudo udevadm test --action=add /sys/class/block/sdb1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文