挂载USB密钥后执行脚本

时间:2019-02-09 15:43:41

标签: bash udev

我尝试运行一个脚本,通过检查其标签来识别USB密钥,并且还具有一个包含标识符的文件。我首先受此启发-> Script not working when evoked by udev rule

首先是udev规则。它可以正常工作并正确调用我的脚本。

KERNEL=="sd[b-z]1", SUBSYSTEM=="block", ACTION=="add", GROUP="plugdev", OWNER="tuxin", RUN+="/home/tuxin/insert-usbkey.sh %k"

这是一个简化为最简单表达的脚本,用于测试操作。

#!/bin/bash
exec </dev/null >/tmp/key-inserted.log 2>&1; PS4=':$LINENO+'; set -x

KEY_LABEL="DEV_JP"

cd /media/tuxin || exit
(
  for ((retries=0; retries<10; retries++)); do
    [[ -d "$KEY_LABEL" ]] && grep -q -e "$KEY_LABEL" /proc/mounts && continue
    sleep 1
  done
  cd "$KEY_LABEL" || exit
  echo "SUCCESS"
) &

不幸的是,尽管安装了密钥,但“ SUCCESS”从未写入日志文件中,其内容为:

:4+KEY_LABEL=DEV_JP
:6+cd /media/tuxin
:8+(( retries=0 ))
:8+(( retries<10 ))
:9+[[ -d DEV_JP ]]
:10+sleep 1

我们可以看到,在“ sleep”命令之后,没有执行任何其他操作。通过进行几次测试,我得出的结论是,一旦安装了密钥,我的脚本就会停止,而在安装密钥时,我什么也不能做。

因此,我继续研究并遵循了此讨论-> how to execute a script every time any USB get mounted

因此,我制定了以下规则,我对此有一些理解上的麻烦,但结果完全相同:

KERNEL!="sd[a-z]*", GOTO="media_by_label_auto_mount_end" ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="media_by_label_auto_mount_end"

# Get label
PROGRAM=="/sbin/blkid -o value -s LABEL %N", ENV{dir_name}="%c"

# use basename to correctly handle labels such as ../mnt/foo
PROGRAM=="/usr/bin/basename '%E{dir_name}'", ENV{dir_name}="%c" ENV{dir_name}=="", ENV{dir_name}="usbhd-%k"

ACTION=="add", ENV{dir_name}!="", RUN+="/bin/su tuxin -c '/usr/bin/pmount %N %E{dir_name}'", RUN+="/home/tuxin/insert-usbkey.sh"

ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/su tuxin -c '/usr/bin/pumount /media/%E{dir_name}'"

LABEL="media_by_label_auto_mount_end"

该脚本在手动启动时可以正常工作,但是由udev执行,一旦装入密钥,在我看来它就被杀死了。自动检测到安装后如何在钥匙上做我想做的事?

以下是在其上测试了此脚本的计算机的摘要(带有或不带有退格操作)。有待了解为什么这在Linux Mint中不起作用。

  Distribution    udev version   Result
  -------------------------------------
  Linux Mint 18       229          KO
  L.M.D.E.            215          OK
  Poky custom.        182          OK
  Linux Mint 18       229          KO
  Lubuntu 18.04       237          OK

1 个答案:

答案 0 :(得分:0)

您的测试脚本在后台子shell 中运行其主要逻辑。因此,它在启动子Shell之后几乎立即完成,因此父bash进程会忠实地向所有子进程发出信号,并在其无能为力之前将其杀死。

不需要背景和子外壳;以下代码可以在我的系统上与udev完美配合:

#!/bin/bash
exec </dev/null >/tmp/key-inserted.log 2>&1; PS4=':$LINENO+'; set -x

KEY_LABEL="DEV_JP"

cd /media/tuxin || exit

for ((retries=0; retries<10; retries++)); do
  [[ -d "$KEY_LABEL" ]] && grep -q -e "$KEY_LABEL" /proc/mounts && break
  sleep 1
done
cd "$KEY_LABEL" || exit
ls .  # Double-check by listing the drive's contents
echo "SUCCESS"

还请注意,我将您的continue更改为break,因为当您找到所需的内容时,这正是您想要做的:突破循环