adds rules to udev

This commit is contained in:
waldek 2021-08-20 13:51:40 +02:00
parent 9c2815190a
commit 6c80ecbd0c
1 changed files with 125 additions and 1 deletions

View File

@ -484,4 +484,128 @@ E: TAGS=:systemd:
We can also inspect information about the **partions** on the disk, even without **mounting** them.
I'll spare you the output of the command but you would do `sudo udevadm info --name=/dev/sdc1` wich gives us the label, type of format, etc.
##
### Using the information
It's nice to *know* more about a device but *doing* something useful is even better.
This is the real beauty of `udev`.
We can use the device information to trigger different actions when a device is added, removed or modified.
This is done by adding **rules** which can be defined in `/etc/udev/rules.d/`.
Let's have a look at what's present on one of my servers.
```
➜ ~ ls -l /etc/udev/rules.d/
total 4
-rw-r--r-- 1 root root 96 Mar 4 12:31 70-persistent-net.rules
➜ ~ cat /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="fa:16:3e:9a:9f:3f", NAME="eth0"
➜ ~
```
This is a rule that fixes the network card with a specific mac address to a fixed name, eth0, each time this device is added.
A complete description of what can be used to form rules and actions can be read in the `man udev` pages.
#### A simple rule
Let's add a rule so that whenever I plug in a specific USB stick, it always has a fixed path in the `/dev` tree.
For this I need find a **unique** value of this USB drive so that my rule will only appy to this specific drive.
I can find the serial number for the first partition by executing `sudo udevadm info --path=/sys/block/sdc -a | grep -E --color=auto 'serial|$'`.
The `grep` command is a handy way of highlighting one specific word (do you understand what the `|$` means?).
Based on the output from this command I can construct the following rule.
```
➜ ~ git:(master) ✗ cat /etc/udev/rules.d/classes.rules
ACTION=="add", ATTRS{serial}=="0101afb5176b84241e77e68fb386ea23b31fe4cf9eafe43b465def85b4531ad93da300000000000000000000014b07c6ff8d260091558107b52921c2", SYMLINK+="sparedisk"
➜ ~ git:(master) ✗
```
Now that the rule has been created we need to tell `udev` to take this new rule into account.
This is very similar to how `systemd` needs a `systemctl daemon-reload` when we make changes to service files.
This is done with the following command.
Once this is done I can plug the drive out and in I'll see my `/dev/sparedisk` apprear!
```
sudo udevadm control --reload
➜ ~ git:(master) ✗ ls /dev/sparedisk -l
ls: cannot access '/dev/sparedisk': No such file or directory
➜ ~ git:(master) ✗ ls /dev/sparedisk -l
lrwxrwxrwx 1 root root 4 Aug 20 13:29 /dev/sparedisk -> sdc1
➜ ~ git:(master) ✗
```
#### A more practical rule
There is a lot more we can do with rules so let's create a more complicated one.
I could like to log every block device connected to the system to a specific file for security monitoring.
For this I'll write a simple `bash` script and a `udev` rule that should trigger at each **add** of a **block** device.
Let's do the rule first.
```
➜ ~ git:(master) ✗ cat /etc/udev/rules.d/classes.rules
SUBSYSTEM=="block", ACTION=="add", RUN="/home/waldek/bin/block_monitor.sh"
➜ ~ git:(master) ✗
```
The script is just a placeholder for now to prove the script get's triggered.
```
➜ ~ git:(master) ✗ cat bin/block_monitor.sh
#!/bin/bash
echo "helloworld: $(date)" >> /tmp/block_monitor.log
➜ ~ git:(master) ✗
```
And after plugging the USB stick in **2** times I get the following output.
Does this look normal to you?
Why are we getting two entries per plug in?
```
➜ ~ git:(master) ✗ cat /tmp/block_monitor.log
helloworld: Fri Aug 20 12:35:42 BST 2021
helloworld: Fri Aug 20 12:35:43 BST 2021
helloworld: Fri Aug 20 12:36:04 BST 2021
helloworld: Fri Aug 20 12:36:04 BST 2021
➜ ~ git:(master) ✗
```
OK, the proof of concept is working but let's make it an actual useful log.
There is a very nice feature hidden in the `man udev` pages towards the end.
I'll outline the base but please go have a look to see what more you can do with it.
```
The NAME, SYMLINK, PROGRAM, OWNER, GROUP, MODE, SECLABEL, and RUN
fields support simple string substitutions. The RUN substitutions
are performed after all rules have been processed, right before
the program is executed, allowing for the use of device
properties set by earlier matching rules. For all other fields,
substitutions are performed while the individual rule is being
processed. The available substitutions are:
```
With this in mind we can pass more information on to our script.
I'll start by using the `%p` and `$name` arguments to the RUN call.
The rule now looks as follows (and I reload the rules to take the changes into account).
```
➜ ~ git:(master) ✗ cat /etc/udev/rules.d/classes.rules
SUBSYSTEM=="block", ACTION=="add", RUN="/home/waldek/bin/block_monitor.sh %p $name"
➜ ~ git:(master) ✗ sudo udevadm control --reload
➜ ~ git:(master) ✗
```
I'll have to modify the script a bit to write these changes to my log file as well.
Remember the `$1` and `$2` meaning in `bash`?
```
➜ ~ git:(master) ✗ cat bin/block_monitor.sh
#!/bin/bash
echo "helloworld: $(date) - $1 - $2" >> /tmp/block_monitor.log
➜ ~ git:(master) ✗ tail -n 4 /tmp/block_monitor.log
helloworld: Fri Aug 20 12:46:29 BST 2021 - /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host6/target6:0:0/6:0:0:0/block/sdc - sdc
helloworld: Fri Aug 20 12:46:29 BST 2021 - /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host6/target6:0:0/6:0:0:0/block/sdc/sdc1 - sdc1
helloworld: Fri Aug 20 12:50:33 BST 2021 - /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host6/target6:0:0/6:0:0:0/block/sdc - sdc
helloworld: Fri Aug 20 12:50:33 BST 2021 - /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host6/target6:0:0/6:0:0:0/block/sdc/sdc1 - sdc1
➜ ~ git:(master) ✗
```