Difference between revisions of "Map Custom Device Entries with udev"

From ArchWiki
Jump to: navigation, search
(Undo revision 81273 by Changaco (Talk) Please don't delete the entire article just because you think it's not useful. It is.)
(removed outdated udev 1.3* information)
Line 1: Line 1:
 
[[Category:Hardware detection and troubleshooting (English)]]
 
[[Category:Hardware detection and troubleshooting (English)]]
 
[[Category:HOWTOs (English)]]
 
[[Category:HOWTOs (English)]]
 
 
{{i18n_links_start}}
 
{{i18n_links_start}}
 
{{i18n_entry|English|Using udev to map multiple entries to a device}}
 
{{i18n_entry|English|Using udev to map multiple entries to a device}}
Line 7: Line 6:
 
{{i18n_links_end}}
 
{{i18n_links_end}}
  
This information is basically mirrored from the gentoo wiki with some additional hints. Recently it was updated to reflect changes in udev >= 98 syntax.
+
This process allows to map a specific device to a constant device-node (in {{filename|/dev}}). This can then be used in {{filename|[[fstab]]}}, among other places, to ensure that the device can be mounted with a unchanging device-node--ideal for desktop shortcuts and shell completion.
 
+
This process allows you to always map a specific device to the same <code>/dev</code> node. This can then be used in <code>fstab</code> to ensure you can always mount the device same device in exactly the same place - which is great for desktop shortcuts!
+
 
+
 
+
==Get the udev info for your USB device==
+
 
+
I've written a small script to do this for you.  Simply plug in the device you want the entry for, then run the script.  I call it "usb-show-serial", and I run it like so:
+
 
+
  root@hobo:/usr/local/sbin/ > ./usb-show-serial /dev/sdb foo
+
  add the following to /etc/udev/rules.d/90-automounter.rules
+
  BUS=="usb", ATTRS{serial}=="23560716050834460007" , KERNEL=="sd?1", NAME="%k", SYMLINK+="foo",  GROUP="storage"
+
 
+
The script is available from here: http://kaizo.org/misc/slackware/current/misc/usb-show-serial
+
 
+
  
 +
This article focuses on USB devices, and was copied almost verbatim from the Gentoo wiki, supplemented with additional hints.
  
 +
==Get USB device udev information==
 +
Here is script that facilitates this operation. Simply plug in the device before running the script. Save it as {{filename|usb-show-serial}}, for example, and run it like so:
 +
{{command|name=./usb-show-serial /dev/''sdX'' ''label''|output=
 +
add the following to /etc/udev/rules.d/90-automounter.rules
 +
BUS=="usb", ATTRS{serial}=="23560716050834460007" , KERNEL=="sd?1", NAME="%k", SYMLINK+="foo",  GROUP="storage"
 +
}}
 +
The script is available [http://kaizo.org/misc/slackware/current/misc/usb-show-serial here].
 
    
 
    
==Manual Method==
+
==Manual method==
 
+
Make sure one of the target devices is plugged in and then run the following (replacing {{filename|sda}} as needed):
Make sure one of your target devices is plugged in and then run the following as root:
+
{{command|name=udevadm info -a -p `udevadm info -q path -n /dev/sda`|output=
udevadm info -a -p `udevadm info -q path -n /dev/sda`
+
 
+
This gets the udev device info for the device on <code>/dev/sda</code> - if your device is not mapped to <code>/dev/sda</code> then obviously use the correct mapping. :)
+
 
+
You should get some output like this:
+
<pre>
+
 
+
 
Udevadm starts with the device specified by the devpath and then
 
Udevadm starts with the device specified by the devpath and then
 
walks up the chain of parent devices. It prints for every device
 
walks up the chain of parent devices. It prints for every device
Line 161: Line 147:
 
     SUBSYSTEMS==""
 
     SUBSYSTEMS==""
 
     DRIVERS==""
 
     DRIVERS==""
 +
}}
  
</pre>
+
The only part of this that is needed is {{codeline|ATTRS{serial}}}, so use {{codeline|grep}} to filter the information:
 +
{{command|name=udevadm info -a -p `udevadm info -q path -n /dev/sda` | grep ATTRS{serial}|output=
 +
  ATTRS{serial}=="14AB0000000096"
 +
  ATTRS{serial}=="0000:00:02.2"
 +
}}
  
Bit too much information!  The only bit of this you actually need is the <code>ATTRS{serial}</code> part - so now you know what the above command does just grep out the bit you want in future cases:
+
This narrows down the search to a much greater degree; however, one of the two serials is unrelevant. Trim down the {{codeline|grep}}:
 
+
{{command|name=udevadm info -a -p `udevadm info -q path -n /dev/sda` | grep ATTRS{product}|output=
udevadm info -a -p `udevadm info -q path -n /dev/sda` | grep ATTRS{serial}
+
  '''ATTRS{product}=="USB Mass Storage Device"'''
 
+
  ATTRS{product}=="EHCI Host Controller"
output:
+
}}
 
+
The first choice is obviously the correct one.
    ATTRS{serial}=="14AB0000000096"
+
    ATTRS{serial}=="0000:00:02.2"
+
 
+
Hmm, two serials. Which one to use?
+
 
+
udevadm info -a -p `udevadm info -q path -n /dev/sda` | grep ATTRS{product}
+
 
+
and we get
+
 
+
    ATTRS{product}=="USB Mass Storage Device"
+
    ATTRS{product}=="EHCI Host Controller"
+
 
+
So, we need to use first serial.
+
 
+
==Create a udev rule==
+
 
+
You then use the <code>ATTRS{serial}</code> in a udev rule as follows:
+
 
+
Note: The convention for Arch Linux is to place custom rules into <code>/etc/udev/rules.d/00.rules</code>
+
You may, however create a file with a different name. Just remember that udev processes these files in alphabetical order.
+
  
 +
==Create udev rule==
 +
Use the {{codeline|ATTRS{serial}}} in a udev rule as follows. Place it in {{filename|/etc/udev/rules.d/00.rules}}:
 
  BUS=="usb", ATTRS{serial}=="14AB0000000096", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbdrive", GROUP="storage"
 
  BUS=="usb", ATTRS{serial}=="14AB0000000096", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbdrive", GROUP="storage"
 +
{{note|When creating a file with a different naming scheme that those in the directory, remember that udev processes these files in alphabetical order.}}
  
 +
==Make fstab entry==
 +
Create a directory for mounting:
 +
# mkdir /mnt/usbdrive
  
==Create an fstab entry and mount point==
+
In {{filename|/etc/[[fstab]]}}, create an entry as:
 +
/dev/usbdrive /mnt/usbdrive vfat rw,noauto,group,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 0 0
  
Create a directory:
+
Options {{codeline|nodev, nosuid, and noexec}} are unnecesary; they are stated for security reasons only. Additionally, depending on your locale preferences, add {{coeline|codepage}} and {{codeline|iocharset}} options (such as {{codeline|codepage=866,iocharset=utf-8}}) in order to be able to display non-Latin file-names correctly.
 
+
  mkdir /mnt/usbdrive
+
 
+
In your <code>/etc/fstab</code>, create an entry like this:
+
 
+
/dev/usbdrive    /mnt/usbdrive    vfat rw,noauto,group,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111    0 0
+
 
+
Additionally, depending on your locale preferences, add something like <code>codepage=866,iocharset=utf-8</code> to be able to see non-Latin filenames correctly.
+
 
+
Now root or any user who belongs to the <code>storage</code> group can mount the USB stick by simply doing
+
  
 +
Now, root and users who belongs to the {{codeline|storage}} [[group]] can mount the USB device by:
 
  mount /mnt/usbdrive
 
  mount /mnt/usbdrive
  
BTW, all the last 3 additional mount options are meant to increase your system's security, e.g. they will prevent you running an executable file directly from the USB drive.
+
To allow a non-root user to access to USB devices, add them to the storage group:
 
+
  # gpasswd -a ''username'' storage
To allow non-root users to access to USB stick do
+
gpasswd -a user1 storage
+
  gpasswd -a user2 storage
+
  
 
==Restart udev==
 
==Restart udev==
 
+
To load the updated rules, run:
To load your updated rules you can run:
+
  # udevadm control --reload-rules
  udevadm control --reload-rules
+
 
+
''Note: As of udev-1.30, the following is deprecated and needs to be updated. It probably won't work anymore.''
+
 
+
Only if really needed, you may restart udev like this. As root, run those 3 commands:
+
/etc/./start_udev
+
mount /dev/pts
+
mount /dev/shm
+
  
 
==Examples==
 
==Examples==
 +
Here are some mapping and mounting examples. This system's devices sometimes made nodes as {{filename|sda}} or {{filename|sda1}} so I two rules for each needed to be specified, which aid "device not found" problems. The {{filename|sda}} node is also needed for disk-level activities; e.g., {{codeline|fdisk /dev/sda}}.
  
Here are some examples from my system.  My devices sometimes mount on <code>sda</code> or <code>sda1</code> so I have two rules for each - this is a work around for device not found problems. The sda node is also needed for disk-level activities e.g. <code>fdisk /dev/sda</code>.
+
This always maps a specific USB device (in this case, a pendrive) to {{filename|/dev/usbpen}}, which is then set in fstab to mount on {{filename|/mnt/usbpen}}:
 
+
This always maps my disgo USB pen to <code>/dev/usbpen</code> which I then map in fstab to mount on <code>/mnt/usbpen</code>
+
 
+
 
  # Symlink USB pen
 
  # Symlink USB pen
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?", NAME="%k", SYMLINK+="usbpen", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?", NAME="%k", SYMLINK+="usbpen", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbpen", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbpen", GROUP="storage"
  
If you have a device with with multiple partitions, the following example maps the device to <code>/dev/usbdisk</code>, and partitions 1, 2, 3 etc. to <code>/dev/usbdisk1</code>, <code>/dev/usbdisk2</code>, <code>/dev/usbdisk3</code> etc.
+
If for devices with multiple partitions, the following example maps the device to {{filename|/dev/usbdisk}}, and partitions 1, 2, 3 etc., to {{filename|/dev/usbdisk1}}, {{filename|/dev/usbdisk2}}, {{filename|/dev/usbdisk3}}, etc.
 
+
 
  # Symlink multi-part device
 
  # Symlink multi-part device
 
  SUSSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?", NAME="%k", SYMLINK+="usbdisk", GROUP="storage"
 
  SUSSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?", NAME="%k", SYMLINK+="usbdisk", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?[1-9]", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?[1-9]", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
  
These rules are equivalent to the following one:
+
The above rules are equivalent to the following one:
 
+
 
  # Symlink multi-part device
 
  # Symlink multi-part device
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd*", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd*", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
  
You can also omit the NAME and GROUP statements, so that the defaults from <code>udev.rules</code> are used. So the shortest and simplest solution would be adding this rule:
+
It's also possible to omit the {{codeline|NAME}} and {{codeline|GROUP}} statements, so that the defaults from {{filename|udev.rules}} are used. Meaning that the shortest and simplest solution would be adding this rule:
 
+
 
  # Symlink multi-part device
 
  # Symlink multi-part device
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd*", SYMLINK+="usbdisk%n"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd*", SYMLINK+="usbdisk%n"
  
This always maps our Olympus digicam to <code>/dev/usbcam</code> which I then map in fstab to mount on <code>/mnt/usbcam</code>
+
This always maps a Olympus digicam to {{filename|/dev/usbcam}}, which can be stated in {{filename|fstab}} to mount on {{filename|/mnt/usbcam}}:
 
+
 
  # Symlink USB camera
 
  # Symlink USB camera
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="000207532049", KERNEL=="sd?", NAME="%k", SYMLINK+="usbcam", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="000207532049", KERNEL=="sd?", NAME="%k", SYMLINK+="usbcam", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="000207532049", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbcam", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="000207532049", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbcam", GROUP="storage"
  
And this maps my Packard Bell MP3 player to <code>/dev/mp3player</code>
+
And this maps a Packard Bell MP3 player to {{filename|/dev/mp3player}}
 
+
 
  # Symlink MP3 player
 
  # Symlink MP3 player
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="0002F5CF72C9C691", KERNEL=="sd?", NAME="%k", SYMLINK+="mp3player", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="0002F5CF72C9C691", KERNEL=="sd?", NAME="%k", SYMLINK+="mp3player", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="0002F5CF72C9C691", KERNEL=="sd?1", NAME="%k", SYMLINK+="mp3player", GROUP="storage"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="0002F5CF72C9C691", KERNEL=="sd?1", NAME="%k", SYMLINK+="mp3player", GROUP="storage"
  
To map your own usb key to <code>/dev/mykey</code> and all of other keys to <code>/dev/otherkey</code>
+
To map a selected usb-key to {{filename|/dev/mykey}} and all of other keys to {{filename|/dev/otherkey}}:
 
+
 
  # Symlink USB keys
 
  # Symlink USB keys
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="insert serial key", KERNEL=="sd?1", NAME="%k", SYMLINK+="mykey"
 
  SUBSYSTEMS=="usb", ATTRS{serial}=="insert serial key", KERNEL=="sd?1", NAME="%k", SYMLINK+="mykey"
 
  SUBSYSTEMS=="usb", KERNEL=="sd?1", NAME="%k", SYMLINK+="otherkey"
 
  SUBSYSTEMS=="usb", KERNEL=="sd?1", NAME="%k", SYMLINK+="otherkey"
 +
Note the order of the lines. Since all the USB keys should create the {{filename|/dev/sd<a||b>}} node, udev will first check if it is a rules-stated USB-key, defined by serial number. But if an unknown USB-key is plugged, it will create ''also'' create a node, using the previously stated generic name, "otherkey". That rule should be the last one in rules file so that it does not override the others.
  
Note the order of the lines. Since all the usb keys should create the /dev/sd<a||b> node, udev will first check if it is your own usb key, defined with the serial number. But if you plug another key witch you don't know the serial number, it will create a node too, with a generic name "otherkey". That rule should be the last one your rules file.
+
This is an example on how to distinguish USB HDD drives and USB sticks:
 
+
 
+
This is an example how to distinguish USB HDD drive and USB sticks:
+
 
+
 
  BUS=="usb", ATTRS{product}=="USB2.0 Storage Device", KERNEL=="sd?", NAME="%k", SYMLINK+="usbdisk", GROUP="storage"
 
  BUS=="usb", ATTRS{product}=="USB2.0 Storage Device", KERNEL=="sd?", NAME="%k", SYMLINK+="usbdisk", GROUP="storage"
 
  BUS=="usb", ATTRS{product}=="USB2.0 Storage Device", KERNEL=="sd?[1-9]", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
 
  BUS=="usb", ATTRS{product}=="USB2.0 Storage Device", KERNEL=="sd?[1-9]", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
 
  BUS=="usb", ATTRS{product}=="USB Mass Storage Device", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbflash", GROUP="storage"
 
  BUS=="usb", ATTRS{product}=="USB Mass Storage Device", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbflash", GROUP="storage"
 
 
Note that this udev rule doesn't use serials at all.
 
Note that this udev rule doesn't use serials at all.

Revision as of 23:47, 9 December 2009

Template:I18n links start Template:I18n entry Template:I18n entry Template:I18n links end

This process allows to map a specific device to a constant device-node (in Template:Filename). This can then be used in Template:Filename, among other places, to ensure that the device can be mounted with a unchanging device-node--ideal for desktop shortcuts and shell completion.

This article focuses on USB devices, and was copied almost verbatim from the Gentoo wiki, supplemented with additional hints.

Get USB device udev information

Here is script that facilitates this operation. Simply plug in the device before running the script. Save it as Template:Filename, for example, and run it like so: Template:Command The script is available here.

Manual method

Make sure one of the target devices is plugged in and then run the following (replacing Template:Filename as needed): Template:Command

The only part of this that is needed is Template:Codeline}, so use Template:Codeline to filter the information: Template:Command

This narrows down the search to a much greater degree; however, one of the two serials is unrelevant. Trim down the Template:Codeline: Template:Command The first choice is obviously the correct one.

Create udev rule

Use the Template:Codeline} in a udev rule as follows. Place it in Template:Filename:

BUS=="usb", ATTRS{serial}=="14AB0000000096", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbdrive", GROUP="storage"
Note: When creating a file with a different naming scheme that those in the directory, remember that udev processes these files in alphabetical order.

Make fstab entry

Create a directory for mounting:

# mkdir /mnt/usbdrive

In Template:Filename, create an entry as:

/dev/usbdrive /mnt/usbdrive vfat rw,noauto,group,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 0 0

Options Template:Codeline are unnecesary; they are stated for security reasons only. Additionally, depending on your locale preferences, add Template:Coeline and Template:Codeline options (such as Template:Codeline) in order to be able to display non-Latin file-names correctly.

Now, root and users who belongs to the Template:Codeline group can mount the USB device by:

mount /mnt/usbdrive

To allow a non-root user to access to USB devices, add them to the storage group:

# gpasswd -a username storage

Restart udev

To load the updated rules, run:

# udevadm control --reload-rules

Examples

Here are some mapping and mounting examples. This system's devices sometimes made nodes as Template:Filename or Template:Filename so I two rules for each needed to be specified, which aid "device not found" problems. The Template:Filename node is also needed for disk-level activities; e.g., Template:Codeline.

This always maps a specific USB device (in this case, a pendrive) to Template:Filename, which is then set in fstab to mount on Template:Filename:

# Symlink USB pen
SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?", NAME="%k", SYMLINK+="usbpen", GROUP="storage"
SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbpen", GROUP="storage"

If for devices with multiple partitions, the following example maps the device to Template:Filename, and partitions 1, 2, 3 etc., to Template:Filename, Template:Filename, Template:Filename, etc.

# Symlink multi-part device
SUSSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?", NAME="%k", SYMLINK+="usbdisk", GROUP="storage"
SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd?[1-9]", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"

The above rules are equivalent to the following one:

# Symlink multi-part device
SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd*", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"

It's also possible to omit the Template:Codeline and Template:Codeline statements, so that the defaults from Template:Filename are used. Meaning that the shortest and simplest solution would be adding this rule:

# Symlink multi-part device
SUBSYSTEMS=="usb", ATTRS{serial}=="1730C13B18000B84", KERNEL=="sd*", SYMLINK+="usbdisk%n"

This always maps a Olympus digicam to Template:Filename, which can be stated in Template:Filename to mount on Template:Filename:

# Symlink USB camera
SUBSYSTEMS=="usb", ATTRS{serial}=="000207532049", KERNEL=="sd?", NAME="%k", SYMLINK+="usbcam", GROUP="storage"
SUBSYSTEMS=="usb", ATTRS{serial}=="000207532049", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbcam", GROUP="storage"

And this maps a Packard Bell MP3 player to Template:Filename

# Symlink MP3 player
SUBSYSTEMS=="usb", ATTRS{serial}=="0002F5CF72C9C691", KERNEL=="sd?", NAME="%k", SYMLINK+="mp3player", GROUP="storage"
SUBSYSTEMS=="usb", ATTRS{serial}=="0002F5CF72C9C691", KERNEL=="sd?1", NAME="%k", SYMLINK+="mp3player", GROUP="storage"

To map a selected usb-key to Template:Filename and all of other keys to Template:Filename:

# Symlink USB keys
SUBSYSTEMS=="usb", ATTRS{serial}=="insert serial key", KERNEL=="sd?1", NAME="%k", SYMLINK+="mykey"
SUBSYSTEMS=="usb", KERNEL=="sd?1", NAME="%k", SYMLINK+="otherkey"

Note the order of the lines. Since all the USB keys should create the Template:Filename node, udev will first check if it is a rules-stated USB-key, defined by serial number. But if an unknown USB-key is plugged, it will create also create a node, using the previously stated generic name, "otherkey". That rule should be the last one in rules file so that it does not override the others.

This is an example on how to distinguish USB HDD drives and USB sticks:

BUS=="usb", ATTRS{product}=="USB2.0 Storage Device", KERNEL=="sd?", NAME="%k", SYMLINK+="usbdisk", GROUP="storage"
BUS=="usb", ATTRS{product}=="USB2.0 Storage Device", KERNEL=="sd?[1-9]", NAME="%k", SYMLINK+="usbdisk%n", GROUP="storage"
BUS=="usb", ATTRS{product}=="USB Mass Storage Device", KERNEL=="sd?1", NAME="%k", SYMLINK+="usbflash", GROUP="storage"

Note that this udev rule doesn't use serials at all.