Translated by qhwdw

This commit is contained in:
qhwdw 2018-12-06 22:36:49 +08:00
parent 3a628916f5
commit f9becedef5
2 changed files with 228 additions and 229 deletions

View File

@ -1,229 +0,0 @@
Translating by qhwdw
An introduction to Udev: The Linux subsystem for managing device events
======
Create a script that triggers your computer to do a specific action when a specific device is plugged in.
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_520x292_opensourceprescription.png?itok=gFrc_GTH)
Udev is the Linux subsystem that supplies your computer with device events. In plain English, that means it's the code that detects when you have things plugged into your computer, like a network card, external hard drives (including USB thumb drives), mouses, keyboards, joysticks and gamepads, DVD-ROM drives, and so on. That makes it a potentially useful utility, and it's well-enough exposed that a standard user can manually script it to do things like performing certain tasks when a certain hard drive is plugged in.
This article teaches you how to create a [udev][1] script triggered by some udev event, such as plugging in a specific thumb drive. Once you understand the process for working with udev, you can use it to do all manner of things, like loading a specific driver when a gamepad is attached, or performing an automatic backup when you attach your backup drive.
### A basic script
The best way to work with udev is in small chunks. Don't write the entire script upfront, but instead start with something that simply confirms that udev triggers some custom event.
Depending on your goal for your script, you can't guarantee you will ever see the results of a script with your own eyes, so make sure your script logs that it was successfully triggered. The usual place for log files is in the **/var** directory, but that's mostly the root user's domain. For testing, use **/tmp** , which is accessible by normal users and usually gets cleaned out with a reboot.
Open your favorite text editor and enter this simple script:
```
#!/usr/bin/bash
echo $date > /tmp/udev.log
```
Place this in **/usr/local/bin** or some such place in the default executable path. Call it **trigger.sh** and, of course, make it executable with **chmod +x**.
```
$ sudo mv trigger.sh /usr/local/bin
$ sudo chmod +x /usr/local/bin/trigger.sh
```
This script has nothing to do with udev. When it executes, the script places a timestamp in the file **/tmp/udev.log**. Test the script yourself:
```
$ /usr/local/bin/trigger.sh
$ cat /tmp/udev.log
Tue Oct 31 01:05:28 NZDT 2035
```
The next step is to make udev trigger the script.
### Unique device identification
In order for your script to be triggered by a device event, udev must know under what conditions it should call the script. In real life, you can identify a thumb drive by its color, the manufacturer, and the fact that you just plugged it into your computer. Your computer, however, needs a different set of criteria.
Udev identifies devices by serial numbers, manufacturers, and even vendor ID and product ID numbers. Since this is early in your udev script's lifespan, be as broad, non-specific, and all-inclusive as possible. In other words, you want first to catch nearly any valid udev event to trigger your script.
With the **udevadm monitor** command, you can tap into udev in real time and see what it sees when you plug in different devices. Become root and try it.
```
$ su
# udevadm monitor
```
The monitor function prints received events for:
* UDEV: the event udev sends out after rule processing
* KERNEL: the kernel uevent
With **udevadm monitor** running, plug in a thumb drive and watch as all kinds of information is spewed out onto your screen. Notice that the type of event is an **ADD** event. That's a good way to identify what type of event you want.
The **udevadm monitor** command provides a lot of good info, but you can see it with prettier formatting with the command **udevadm info** , assuming you know where your thumb drive is currently located in your **/dev** tree. If not, unplug and plug your thumb drive back in, then immediately issue this command:
```
$ su -c 'dmesg | tail | fgrep -i sd*'
```
If that command returned **sdb: sdb1** , for instance, you know the kernel has assigned your thumb drive the **sdb** label.
Alternately, you can use the **lsblk** command to see all drives attached to your system, including their sizes and partitions.
Now that you have established where your drive is located in your filesystem, you can view udev information about that device with this command:
```
# udevadm info -a -n /dev/sdb | less
```
This returns a lot of information. Focus on the first block of info for now.
Your job is to pick out parts of udev's report about a device that are most unique to that device, then tell udev to trigger your script when those unique attributes are detected.
The **udevadm info** process reports on a device (specified by the device path), then "walks" up the chain of parent devices. For every device found, it prints all possible attributes using a key-value format. You can compose a rule to match according to the attributes of a device plus attributes from one single parent device.
```
looking at device '/devices/000:000/blah/blah//block/sdb':
  KERNEL=="sdb"
  SUBSYSTEM=="block"
  DRIVER==""
  ATTR{ro}=="0"
  ATTR{size}=="125722368"
  ATTR{stat}==" 2765 1537 5393"
  ATTR{range}=="16"
  ATTR{discard\_alignment}=="0"
  ATTR{removable}=="1"
  ATTR{blah}=="blah"
```
A udev rule must contain one attribute from one single parent device.
Parent attributes are things that describe a device from the most basic level, such as it's something that has been plugged into a physical port or it is something with a size or this is a removable device.
Since the KERNEL label of **sdb** can change depending upon how many other drives were plugged in before you plugged that thumb drive in, that's not the optimal parent attribute for a udev rule. However, it works for a proof of concept, so you could use it. An even better candidate is the SUBSYSTEM attribute, which identifies that this is a "block" system device (which is why the **lsblk** command lists the device).
Open a file called **80-local.rules** in **/etc/udev/rules.d** and enter this code:
```
SUBSYSTEM=="block", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"
```
Save the file, unplug your test thumb drive, and reboot.
Wait, reboot on a Linux machine?
Theoretically, you can just issue **udevadm control --reload** , which should load all rules, but at this stage in the game, it's best to eliminate all variables. Udev is complex enough, and you don't want to be lying in bed all night wondering if that rule didn't work because of a syntax error or if you just should have rebooted. So reboot regardless of what your POSIX pride tells you.
When your system is back online, switch to a text console (with Ctl+Alt+F3 or similar) and plug in your thumb drive. If you are running a recent kernel, you will probably see a bunch of output in your console when you plug in the drive. If you see an error message such as Could not execute /usr/local/bin/trigger.sh, you probably forgot to make the script executable. Otherwise, hopefully all you see is a device was plugged in, it got some kind of kernel device assignment, and so on.
Now, the moment of truth:
```
$ cat /tmp/udev.log
Tue Oct 31 01:35:28 NZDT 2035
```
If you see a very recent date and time returned from **/tmp/udev.log** , udev has successfully triggered your script.
### Refining the rule into something useful
The problem with this rule is that it's very generic. Plugging in a mouse, a thumb drive, or someone else's thumb drive will indiscriminately trigger your script. Now is the time to start focusing on the exact thumb drive you want to trigger your script.
One way to do this is with the vendor ID and product ID. To get these numbers, you can use the **lsusb** command.
```
$ lsusb
Bus 001 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 002 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 003 Device 005: ID 03f0:3307 TyCoon Corp.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 hub
Bus 001 Device 003: ID 13d3:5165 SBo Networks
```
In this example, the **03f0:3307** before **TyCoon Corp.** denotes the idVendor and idProduct attributes. You can also see these numbers in the output of **udevadm info -a -n /dev/sdb | grep vendor** , but I find the output of **lsusb** a little easier on the eyes.
You can now include these attributes in your rule.
```
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/thumb.sh"
```
Test this (yes, you should still reboot, just to make sure you're getting fresh reactions from udev), and it should work the same as before, only now if you plug in, say, a thumb drive manufactured by a different company (therefore with a different idVendor) or a mouse or a printer, the script won't be triggered.
Keep adding new attributes to further focus in on that one unique thumb drive you want to trigger your script. Using **udevadm info -a -n /dev/sdb** , you can find out things like the vendor name, sometimes a serial number, or the product name, and so on.
For your own sanity, be sure to add only one new attribute at a time. Most mistakes I have made (and have seen other people online make) is to throw a bunch of attributes into their udev rule and wonder why the thing no longer works. Testing attributes one by one is the safest way to ensure udev can identify your device successfully.
### Security
This brings up the security concerns of writing udev rules to automatically do something when a drive is plugged in. On my machines, I don't even have auto-mount turned on, and yet this article proposes scripts and rules that execute commands just by having something plugged in.
Two things to bear in mind here.
1. Focus your udev rules once you have them working so they trigger scripts only when you really want them to. Executing a script that blindly copies data to or from your computer is a bad idea in case anyone who happens to be carrying the same brand of thumb drive plugs it into your box.
2. Do not write your udev rule and scripts and forget about them. I know which computers have my udev rules on them, and those boxes are most often my personal computers, not the ones I take around to conferences or have in my office at work. The more "social" a computer is, the less likely it is to get a udev rule on it that could potentially result in my data ending up on someone else's device or someone else's data or malware on my device.
In other words, as with so much of the power provided by a GNU system, it is your job to be mindful of how you are wielding that power. If you abuse it or fail to treat it with respect, it very well could go horribly wrong.
### Udev in the real world
Now that you can confirm that your script is triggered by udev, you can turn your attention to the function of the script. Right now, it is useless, doing nothing more than logging the fact that it has been executed.
I use udev to trigger [automated backups][2] of my thumb drives. The idea is that the master copies of my active documents are on my thumb drive (since it goes everywhere I go and could be worked on at any moment), and those master documents get backed up to my computer each time I plug the drive into that machine. In other words, my computer is the backup drive and my production data is mobile. The source code is available, so feel free to look at the code of attachup for further examples of constraining your udev tests.
Since that's what I use udev for the most, it's the example I'll use here, but udev can grab lots of other things, like gamepads (this is useful on systems that aren't set to load the xboxdrv module when a gamepad is attached) and cameras and microphones (useful to set inputs when a specific mic is attached), so realize that it's good for a lot more than this one example.
A simple version of my backup system is a two-command process:
```
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", SYMLINK+="safety%n"
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"
```
The first line detects my thumb drive with the attributes already discussed, then assigns the thumb drive a symlink within the device tree. The symlink it assigns is **safety%n**. The **%n** is a udev macro that resolves to whatever number the kernel gives to the device, such as sdb1, sdb2, sdb3, and so on. So **%n** would be the 1 or the 2 or the 3.
This creates a symlink in the dev tree, so it does not interfere with the normal process of plugging in a device. This means that if you use a desktop environment that likes to auto-mount devices, you won't be causing problems for it.
The second line runs the script.
My backup script looks like this:
```
#!/usr/bin/bash
mount /dev/safety1 /mnt/hd
sleep 2
rsync -az /mnt/hd/ /home/seth/backups/ && umount /dev/safety1
```
The script uses the symlink, which avoids the possibility of udev naming the drive something unexpected (for instance, if I have a thumb drive called DISK plugged into my computer already, and I plug in my other thumb drive also called DISK, the second one will be labeled DISK_, which would foil my script). It mounts **safety1** (the first partition of the drive) at my preferred mount point of **/mnt/hd**.
Once safely mounted, it uses [rsync][3] to back up the drive to my backup folder (my actual script uses rdiff-backup, and yours can use whatever automated backup solution you prefer).
### Udev is your dev
Udev is a very flexible system and enables you to define rules and functions in ways that few other systems dare provide users. Learn it and use it, and enjoy the power of POSIX.
This article builds on content from the [Slackermedia Handbook][4], which is licensed under the [GNU Free Documentation License 1.3][5].
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/11/udev
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://linux.die.net/man/8/udev
[2]: https://gitlab.com/slackermedia/attachup
[3]: https://opensource.com/article/17/1/rsync-backup-linux
[4]: http://slackermedia.info/handbook/doku.php?id=backup
[5]: http://www.gnu.org/licenses/fdl-1.3.html

View File

@ -0,0 +1,228 @@
Udev 入门:管理设备事件的 Linux 子系统
======
创建这样一个脚本,当指定的设备插入时触发你的计算机去做一个指定动作。
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_520x292_opensourceprescription.png?itok=gFrc_GTH)
Udev 是一个让你的计算机使用设备事件的 Linux 子系统。通俗来讲就是,当你的计算机上插入了像网卡、外置硬盘(包括 U 盘、鼠标、键盘、游戏操纵杆和手柄、DVD-ROM 驱动器等等设备时,代码能够检测到它们。这样就能写出很多可能非常有用的实用程序,而它已经很好了,普通用户就可以写出脚本去做一些事情,比如当某个硬盘驱动器插入时,执行某个任务。
这篇文章教你去如何写一个由一些 udev 事件触发的 [udev][1] 脚本,比如插入了一个 U 盘。当你理解了 udev 的工作原理,你就可以用它去做各种事情,比如当一个游戏手柄连接后加载一个指定的驱动程序,或者当你用于备份的驱动器连接后,自动执行备份工作。
### 一个初级的脚本
使用 udev 的最佳方式是让它工作在一个小的代码块中。不要指望从一开始就写出完整的脚本,而是从最简单的确认 udev 触发了某些指定的事件开始。
对于你的脚本,依据你的目标,并不是在任何情况下都能保证你亲眼看到你的脚本运行结果的,因此需要在你的脚本日志中确认它成功触发了。而日志文件通常放在 **/var** 目录下,但那个目录通常是 root 用户的领地。对于测试目的,可以使用 **/tmp**,它可以被普通用户访问并且在重启动后就被清除了。
打开你喜欢的文本编辑器,然后输入下面的简单脚本:
```
#!/usr/bin/bash
echo $date > /tmp/udev.log
```
把这个脚本放在 **/usr/local/bin** 或缺省可运行路径的位置中。将它命名为 **trigger.sh**,并运行 **chmod +x** 授予可运行权限:
```
$ sudo mv trigger.sh /usr/local/bin
$ sudo chmod +x /usr/local/bin/trigger.sh
```
udev 用这个脚本并不做任何事情。当它运行时,这个脚本将在文件 **/tmp/udev.log** 中放入当前的时间戳。你可以自己测试一下这个脚本:
```
$ /usr/local/bin/trigger.sh
$ cat /tmp/udev.log
Tue Oct 31 01:05:28 NZDT 2035
```
接下来让 udev 去触发这个脚本。
### 唯一设备识别
为了让你的脚本能够被一个设备事件触发udev 必须要知道在什么情况下调用该脚本。在现实中,你可以通过它的颜色、制造商、以及插入到你的计算机这一事实来识别一个 U 盘。而你的计算机,它需要一系列不同的标准。
Udev 通过序列号、制造商、以及提供商 ID 和产品 ID 号来识别设备。由于现在你的 udev 脚本还处于它的生命周期的早期阶段,因此要尽可能地宽泛、非特定和全包括。换句话说就是,你希望首先去捕获尽可能多的有效 udev 事件来触发你的脚本。
使用 **udevadm monitor** 命令你可以实时利用 udev并且可以看到当你插入不同设备时发生了什么。用 root 权限试一试。
```
$ su
# udevadm monitor
```
监视函数输出接收到的事件:
* UDEV在规则处理之后发出 udev 事件
* KERNEL内核发送 uevent 事件
**udevadm monitor** 命令运行时,插入一个 U 盘,你将看到各种信息在你的屏幕上滚动而出。注意那一个 **ADD** 事件的事件类型。这是你所需要的识别事件类型的一个好方法。
**udevadm monitor** 命令提供了许多很好的信息,但是你可以使用 **udevadm info** 命令以更好看的格式来看到它,假如你知道你的 U 盘当前已经位于你的 **/dev** 树。如果不在这个树下,拔下它并重新插入,然后立即运行这个命令:
```
$ su -c 'dmesg | tail | fgrep -i sd*'
```
举例来说,如果那个命令返回 **sdb: sdb1**,说明内核已经给你的 U 盘分配了 **sdb** 卷标。
或者,你可以使用 **lsblk** 命令去查看所有附加到你的系统上的驱动器,包括它的大小和分区。
现在,你的驱动器已经处于你的文件系统中了,你可以使用下面的命令去查看那个设备的相关 udev 信息:
```
# udevadm info -a -n /dev/sdb | less
```
这个命令将返回许多信息。现在我们只关心信息中的第一个块。
你的任务是从 udev 的报告中找出能唯一标识那个设备的部分,然后当计算机检测到这些唯一属性时,告诉 udev 去触发你的脚本。
**udevadm info** 命令处理一个(由设备路径指定的)设备上的报告,接着“遍历”父级设备链。对于找到的大多数设备,它以一个“键值对”格式输出所有可能的属性。你可以写一个规则,从一个单个的父级设备属性上去匹配插入设备的属性。
```
looking at device '/devices/000:000/blah/blah//block/sdb':
  KERNEL=="sdb"
  SUBSYSTEM=="block"
  DRIVER==""
  ATTR{ro}=="0"
  ATTR{size}=="125722368"
  ATTR{stat}==" 2765 1537 5393"
  ATTR{range}=="16"
  ATTR{discard\_alignment}=="0"
  ATTR{removable}=="1"
  ATTR{blah}=="blah"
```
一个 udev 规则必须包含来自单个父级设备的一个属性。
父级属性是描述一个设备的最基本的东西,比如它是插入到一个物理端口的东西、或是一个多大的东西、或这是一个可移除的设备。
由于内核卷标 **sdb** 可能会由于分配给在它之前插入的其它驱动器而发生变化,因此卷标并不是一个 udev 规则的父级属性的好选择。但是,在做概念论证时你可以使用它。一个事件的最佳候选者是 SUBSYSTEM 属性,它表示那个设备是一个 “block” 系统设备(也就是为什么我们要使用 **lsblk** 命令来列出设备的原因)。
**/etc/udev/rules.d** 目录中打开一个名为 **80-local.rules** 的文件,然后输入如下代码:
```
SUBSYSTEM=="block", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"
```
保存文件,拔下你的测试 U 盘,然后重启动系统。
等等,重启动 Linux 机器?
理论上说,你只需要运行 **udevadm control —reload** 即可它将重新加载所有规则但是在我们实验的现阶段最好要排除可能影响实验结果的所有因素。Udev 是非常复杂的,为了不让你躺在床上整晚都在思考为什么这个规则不能正常工作,是因为语法错误吗?还是应该重启动一下。所以,不管 POSIX 自负地告诉你过什么,你都应该去重启动一下。
当你的系统重启动完毕之后,(使用 Ctl+Alt+F3 或类似快捷键)切换到一个文本控制台,并插入你的 U 盘。如果你运行了一个最新的内核,当你插入 U 盘后你或许可以看到一大堆输出。如果看到一个错误信息,比如 “Could not execute /usr/local/bin/trigger.sh”或许是因为你忘了授予这个脚本可运行的权限。否则你将看到的是一个设备插入它得到内核设备分配的一些东西等等。
现在,见证奇迹的时刻到了。
```
$ cat /tmp/udev.log
Tue Oct 31 01:35:28 NZDT 2035
```
如果你在 **/tmp/udev.log** 中看到了最新的日期和时间,那么说明 udev 已经成功触发了你的脚本。
### 改进规则做一些有用的事情
现在的问题是使用的规则太通用了。插入一个鼠标、一个 U 盘、或某个人的 U 盘都将盲目地触发这个脚本。现在,我们开始专注于希望触发你的脚本的是确定的某个 U 盘。
实现上述目标的一种方式是使用提供商 ID 和产品 ID。你可以使用 **lsusb** 命令去得到这些数字。
```
$ lsusb
Bus 001 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 002 Device 002: ID 8087:0024 Slacker Corp. Hub
Bus 003 Device 005: ID 03f0:3307 TyCoon Corp.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 hub
Bus 001 Device 003: ID 13d3:5165 SBo Networks
```
在这个例子中,**TyCoon Corp** 前面的 **03f0:3307** 就表示了提供商 ID 和产品 ID 的属性。你也可以通过 **udevadm info -a -n /dev/sdb | grep vendor** 的输出来查看这些数字,但是从 **lsusb** 的输出中可以很容易地一眼找到这些数字。
现在,可以在你的脚本中包含这些属性了。
```
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/thumb.sh"
```
测试它(是的,为了确保不会有来自 udev 的影响因素,我们仍然建议先重新启动一下),它应该会像前面一样工作,现在,如果你插入一个不同公司制造的 U 盘(因为它们的提供商 ID 不一样)、或插入一个鼠标、或插入一个打印机,这个脚本将不会被触发。
继续添加新属性来进一步专注于你希望去触发你的脚本的那个唯一的 U 盘。使用 **udevadm info -a -n /dev/sdb** 命令,你可以找出像提供商名字、序列号、或产品名这样的东西。
为了保证思路清晰,确保每次只添加一个新属性。我们(和在网上看到的其他人)在 udev 规则中所遇到的大多数错误都是因为一次添加了太多的属性,而奇怪为什么不能正常工作了。逐个测试属性是最安全的作法,这样可以确保 udev 能够成功识别到你的设备。
### 安全
编写 udev 规则当插入一个驱动器后自动去做一些事情,将带来安全方面的担忧。在我的机器上,我甚至都没有打开自动挂载功能,而基于本文的目的,当设备插入时,脚本和规则可以运行一些命令来做一些事情。
在这里需要记住两个事情。
1. 聚焦于你的 udev 规则,当你真实地使用它们时,一旦让规则发挥作用将触发脚本。执行一个脚本去盲目地复制数据到你的计算上,或从你的计算机上复制出数据,是一个很糟糕的主意,因为有可能会遇到一个人拿着和你相同品牌的 U 盘插入到你的机器上的情况。
2. 不要在写了 udev 规则和脚本后忘记了它们的存在。我知道哪个计算上有我的 udev 规则,这些机器一般是我的个人计算机,而不是那些我带着去开会或办公室工作的计算机。一台计算机的 “社交” 程度越高,它就越不能有 udev 规则存在于它上面,因为它将潜在地导致我的数据最终可能会出现在某个人的设备、或某个人的数据中、或在我的设备上出现恶意程序。
换句话说就是,随着一个 GNU 系统提供了一个这么强大的功能,你的任务是小心地如何使用它们的强大功能。如果你滥用它或不小心谨慎地使用它,最终将让你出问题,它非常可能会导致可怕的问题。
### 现实中的 Udev
现在,你可以确认你的脚本是由 udev 触发的,那么,可以将你的关注点转到脚本功能上了。到目前为止,这个脚本是没有用的,它除了记录脚本已经运行过了这一事实外,再没有做更多的事情。
我使用 udev 去触发我的 U 盘的 [自动备份][2] 。这个创意是,将我正在处理的文档的主复本保存在我的 U 盘上(因为我随身带着它,这样就可以随时处理它),并且在我每次将 U 盘插入到那台机器上时,这些主文档将备份回我的计算机上。换句话说就是,我的计算机是备份驱动器,而产生的数据是移动的。源代码是可用的,你可以随意查看 attachup 的代码,以进一步限制你的 udev 的测试示例。
虽然我使用 udev 最多的情况就是这个例子,但是 udev 能抓取很多的事件,像游戏手柄(当连接游戏手柄时,让系统去加载 xboxdrv 模块)、摄像头、麦克风(当指定的麦克风连接时用于去设置输入),所以应该意识到,它能做的事情远比这个示例要多。
我的备份系统的一个简化版本是由两个命令组成的一个过程:
```
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", SYMLINK+="safety%n"
SUBSYSTEM=="block", ATTRS{idVendor}=="03f0", ACTION=="add", RUN+="/usr/local/bin/trigger.sh"
```
第一行使用属性去检测我的 U 盘,这在前面已经讨论过了,接着在设备树中为我的 U 盘分配一个符号链接,给它分配的符号连接是 **safety%n**。这个 **%n** 是一个 udev 宏,它是内核分配给这个设备的任意数字,比如 sdb1、sdb2、sdb3、等等。因此 **%n** 应该是 1 或 2 或 3。
这将在 dev 树中创建一个符号链接,因此它不会干涉插入一个设备的正常过程。这意味着,如果你在自动挂载设备的桌面环境中使用它,将不会出现问题。
第二行运行这个脚本。
我的备份脚本如下:
```
#!/usr/bin/bash
mount /dev/safety1 /mnt/hd
sleep 2
rsync -az /mnt/hd/ /home/seth/backups/ && umount /dev/safety1
```
这个脚本使用符号链接,这将避免出现 udev 命名导致的意外情况(例如,假设一个命名为 DISK 的 U 盘已经插入到我的计算机上,而我插入的其它 U 盘恰好名字也是 DISK那么第二个 U 盘的卷标将被命名为 `DISK_`,这将导致我的脚本不会正常运行),它在我喜欢的挂载点 **/mnt/hd** 上挂载了 **safety1**(驱动器的第一个分区)。
一旦 safely 挂载之后,它将使用 [rsync][3] 将驱动器备份到我的备份文件夹(我真实使用的脚本用的是 rdiff-backup而你可以使用任何一个你喜欢的自动备份解决方案
### Udev 让你的设备你做主
Udev 是一个非常灵活的系统,它可以让你用其它系统很少敢提供给用户的方式去定义规则和功能。学习它,使用它,去享受 POSIX 的强大吧。
本文内容来自 [Slackermedia Handbook][4],它以 [GNU Free Documentation License 1.3][5] 许可证授权使用。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/11/udev
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[qhwdw](https://github.com/qhwdw)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://linux.die.net/man/8/udev
[2]: https://gitlab.com/slackermedia/attachup
[3]: https://opensource.com/article/17/1/rsync-backup-linux
[4]: http://slackermedia.info/handbook/doku.php?id=backup
[5]: http://www.gnu.org/licenses/fdl-1.3.html