| |
---|
| | |
---|
| | Another way to do this is to restart the ``udev`` daemon or reboot to |
---|
| | get the latest rules read in. Note that the daemon restart procedure |
---|
| | is also distro-specific, so you'll have to figure out what works on |
---|
| | your system. |
---|
| | your system. Rebooting is not distro-specific and can always be |
---|
| | accomplished by removing all power sources. This is not a recommended |
---|
| | best practice unless there is loud knocking at the door and |
---|
| | you *really* have to leave fast. |
---|
| | |
---|
| | |
---|
| | Our Example Rules |
---|
| | ================= |
---|
| |
---|
| | rule below is broken across multiple lines to make it more readable, |
---|
| | but it is all on one line in the actual rules file. It is possible to |
---|
| | break rules across lines but you have to ensure that you follow the |
---|
| | syntax that ``udev`` expects. To keep things from mysteriously |
---|
| | breaking, I typically put the entire rule one one line:: |
---|
| | breaking, it is best to put the entire rule one one line:: |
---|
| | |
---|
| | ACTION=="add", KERNEL=="sd*", PROGRAM=="/sbin/scsi_id --whitelisted /dev/$name", |
---|
| | RESULT=="VBOX_HARDDISK_VB5f712327-2bb4be0c", SYMLINK+="my_fine_disk01", |
---|
| | OWNER:="3009", GROUP:="421", MODE:="0600", |
---|
| |
---|
| | the thing that was previously matched*. But, you're not restricted to |
---|
| | this. It's entirely possible to write a rule that operates on |
---|
| | something completely unrelated to the matched condition. For |
---|
| | instance, you could write a rule that says, *reboot the computer |
---|
| | every time my little brother plugs in his favorite thumbdrive*. (This |
---|
| | is, however, considered very bad manners and may get you sent to your |
---|
| | room without dinner.) |
---|
| | every time my little brother plugs in his favorite thumbdrive*. This |
---|
| | is, however, considered Very Bad Manners and may get you sent to your |
---|
| | room without dinner. You may, however, have a career developing |
---|
| | websites for the US government healthcare initiatives. |
---|
| | |
---|
| | Let's take each rule apart, one key-value pair at a time: |
---|
| | |
---|
| | |
---|
| |
---|
| | drive is being *added*. We want to ignore other kernel messages |
---|
| | with ``sd*`` in them when drives are removed or reporting an error. |
---|
| | So, we also include the ``ACTION="add"`` key value pair. |
---|
| | |
---|
| | Effeectively, this lets us look at every drive being added to the |
---|
| | Effectively, this lets us look at every drive being added to the |
---|
| | system, so we can spot the one we're looking for. |
---|
| | |
---|
| | - ``PROGRAM=="/sbin/scsi_id --whitelisted /dev/$name"``, |
---|
| | ``RESULT=="VBOX_HARDDISK_VB5f712327-2bb4be0c"`` |
---|
| |
---|
| | Basically, you have to set ``disk.EnableUUID = "TRUE"`` |
---|
| | in your virtual machine's ``.vmx`` file. |
---|
| | |
---|
| | Why are we bothering with all this? When disks are added and/or |
---|
| | removed from a system, *they are NOT guaranteed to be assigned to |
---|
| | the same device node in* ``/dev/``. Your drive could show up as |
---|
| | ``/dev/sdh`` one time and ``/dev/sdx`` the next. This is the |
---|
| | price we pay for having a dynamic device system that allows hot |
---|
| | swapping USB devices on your laptop or live presentation of SAN |
---|
| | storage to a server. We thus have to use something that |
---|
| | *uniquely* identifies the drive every time. |
---|
| | removed from a system, *they are NOT guaranteed to be assigned to the |
---|
| | same device node in* ``/dev/``. Your drive could show up as |
---|
| | ``/dev/sdh`` one time and ``/dev/sdx`` the next. This is the price we |
---|
| | pay for having a dynamic device system that allows hot swapping USB |
---|
| | devices on your laptop or live presentation of SAN storage to a |
---|
| | server. We thus have to use something that *uniquely* identifies the |
---|
| | drive every time. |
---|
| | |
---|
| | Many of the tutorial examples of this on the World Weird Web show this |
---|
| | "uniqueness" test using the major- and minor device numbers. This is |
---|
| | an Officially Bad Idea (tm) because there is no guarantee that the |
---|
| | same device will get the same major/minor device numbers every time. |
---|
| | These numbers are generated by the kernel and are based on the order |
---|
| | of driver/device loading, the next free number available to the |
---|
| | kernel, and the cosmic ray count in Goscratchistan. Only the |
---|
| | ``wwid`` (or an equivalent ``UUID``) is guaranteed to be unique, so |
---|
| | that's what we used here. |
---|
| | |
---|
| | If we got this far, it means that all our matching tests were |
---|
| | successful: we've found the drive we're looking for. Now we can do |
---|
| | what we set out to do in the first place: |
---|
| |
---|
| | means, *"Add another symbolic link to this mountpoint."* |
---|
| | |
---|
| | The real purpose of this is to provide a *consistent device name* |
---|
| | for software to use when referencing this disk. Say I'm writing |
---|
| | an application. I don't have to know where the disk is mounted. |
---|
| | I just have to always refer to ``/dev/my_fine_disk01`` and let all |
---|
| | this ``udev`` magic do the hard stuff. Remember, it's our job as |
---|
| | Snotty Systems Engineers to relieve Applications Programmers of as |
---|
| | much thinking as possible. Really, it is. Look in the job |
---|
| | description. |
---|
| | an application. We don't have to know where the disk is mounted. |
---|
| | We just have to always refer to ``/dev/my_fine_disk01`` and let |
---|
| | all this ``udev`` magic do the hard stuff. Remember, it's our job |
---|
| | as Snotty Systems Engineers (sm) to relieve Applications Programmers of |
---|
| | as much thinking as possible. Really, it is. Look it up in the |
---|
| | job description. |
---|
| | |
---|
| | |
---|
| | .. NOTE:: Why use a symlink? Why not just rename the mountpoint. |
---|
| | It *is* possible to do this with ``udev`` with the |
---|
| | ``NAME+=...`` key-value construct. I prefer not to do |
---|
| | ``NAME+=...`` key-value construct. It's best not to do |
---|
| | this because you lose visibility into the underlying |
---|
| | device name when you do this. |
---|
| | |
---|
| | It's handy to know that the actual device name is, say, |
---|
| | ``sdk``. For example, ejecting SAN-attached storage |
---|
| | requires you to sent things to |
---|
| | requires you to send things to |
---|
| | ``/sys/block/sdk/device/delete``. If you overwrite |
---|
| | ``/dev/sdk`` with ``my_fine_disk01``, it's not |
---|
| | immediately clear what the underlying device actually |
---|
| | is. A symbolic link covers both bases. |
---|
| |
---|
| | Here the use of the ``+=`` operator means something different. It |
---|
| | means, *"I am the final rule in this matter. No subsequent rule |
---|
| | can change this setting."* That's how we prevent rules that are |
---|
| | read after us (ones with higher numbers in their name) from |
---|
| | overriding what we want. For example, on at least one system |
---|
| | I worked on, using ``GROUP=`` got overriden by a later |
---|
| | default filesystem rule that always reset group ownership to |
---|
| | overriding what we want. For example, we've seen instances of |
---|
| | systems using ``GROUP=`` that then got overriden by a later |
---|
| | default filesystem rule. This then reset group ownership to |
---|
| | ``disk``. Using ``:=`` instead, fixed this. |
---|
| | |
---|
| | One other thing here: Notice the use of numeric values for ``UID`` |
---|
| | and ``GID``. You *could* use the actual user- and group names |
---|
| |
---|
| | |
---|
| | "But why", you may ask, "are you using the ``RUN==`` construct? |
---|
| | Isn't that what ``PROGRAM==`` does?" Not exactly, Grasshopper. |
---|
| | ``PROGRAM==`` *always* runs regardless of prior matching. |
---|
| | ``RUN==`` *only* runs if all prior matching has been succesful. |
---|
| | ``RUN==`` *only* runs if all prior matching has been successful. |
---|
| | |
---|
| | Why is that important here? Say we boot the system, and the |
---|
| | kernel discovers drives ``/dev/sdh, /dev/sdi,`` and ``/dev/sdj`` |
---|
| | and let's suppose that the first one has the matching ``wwid``. |
---|
| | With ``RUN==`` the raw character device will only be created when |
---|
| | the full set of matching occurs - i.e., When the kernel reports |
---|
| | the addition of ``/dev/sdh``. But if you use ``PROGRAM==``, the |
---|
| | raw device will be associated *every time the kernel reports a new |
---|
| | ``/dev/sd*``. The last one to be reported will "win". In this |
---|
| | ``/dev/sd*``*. The last one to be reported will "win". In this |
---|
| | case, that means ``/dev/raw/raw1`` will be associated with |
---|
| | ``/dev/sdj`` - not what we want here. Do NOT email me asking how |
---|
| | I figured this out. It wasn't fun. |
---|
| | ``/dev/sdj`` - not what we want here. |
---|
| | |
---|
| | |
---|
| | With that under our belts, the second rule should be pretty |
---|
| | simple to understand: |
---|
| |
---|
| | we just did that at the end of the previous rule. |
---|
| | |
---|
| | - ``SYMLINK+="rmy_fine_disk01"`` |
---|
| | |
---|
| | Let's symlink ``/dev/raw/raw1`` to ``/dev/rmy_fine_disk01``. The |
---|
| | DBAs can then configure their database engines to look for the |
---|
| | Let's symlink ``/dev/raw/raw1`` to ``/dev/rmy_fine_disk01``. |
---|
| | It is a time honored ``Unix`` convention that the raw device |
---|
| | name be the same as the actual device with an ``r`` prepended |
---|
| | to it. You don't have to do this, but if you don't, people |
---|
| | will hate youu, your dog will probably run away, and your |
---|
| | ex-wife will show up again ... and no one wants that. |
---|
| | |
---|
| | The DBAs can then configure their database engines to look for the |
---|
| | symlink name and never worry about what the underlying node |
---|
| | mapping is for the raw device. Just as with Applications |
---|
| | Programmers, we Snotty Systems Engineers are required - by law - |
---|
| | to make things as easy as possible for DBAs. Again, I refer you |
---|
| | to the job description. |
---|
| | Programmers, we Snotty Systems Engineers (sm) are required - by law - |
---|
| | to make things as easy as possible for DBAs. Again, you are |
---|
| | referred to the job description. |
---|
| | |
---|
| | |
---|
| | - ``OWNER:="3009", GROUP:="421", MODE:="0600`` |
---|
| | |
---|
| |
---|
| | would be a matter of changing the unique ID for the ``RESULT`` field |
---|
| | of the first rule. You'd also have to change any references to |
---|
| | ``my_fine_disk01`` and ``raw1``. |
---|
| | |
---|
| | You'll also have to change the rules above to the program used to |
---|
| | check for a unique ``wwid`` or ``UUID`` on your particular distro. |
---|
| | |
---|
| | If you want to know the current state of what raw devices exist |
---|
| | do this:: |
---|
| | |
---|
| | raw -qa |
---|
| |
---|
| | device, use this, substituting your device for ``/dev/sdd`` :: |
---|
| | |
---|
| | udevadm info --query=all --name /dev/sdd 2>&1| less |
---|
| | |
---|
| | The output of this command can be helful in figuring out just which |
---|
| | The output of this command can be helpful in figuring out just which |
---|
| | attributes and values you need to get to a running rule. |
---|
| | |
---|
| | Finally, you can test your rules to see what is matching, again |
---|
| | substituting for ``/block/sdd``:: |
---|
| |
---|
| | |
---|
| | Document Revision Information |
---|
| | ============================= |
---|
| | |
---|
| | ``$Id: Deconstructing_Linux_udev_Rules.rst,v 1.112 2013/11/01 02:17:08 tundra Exp $`` |
---|
| | ``$Id: Deconstructing_Linux_udev_Rules.rst,v 1.113 2013/11/01 02:53:07 tundra Exp $`` |
---|
| | |
---|
| | You can find the latest version of this document at: |
---|
| | |
---|
| | http://www.tundraware.com/TechnicalNotes/Deconstructing-Linux-udev-Rules |
---|
| | |