Get device node by major/minor numbers pair
Each device node under /dev
has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat
, like this:
stat -c 'major: %t minor: %T' <file>
Or, ls -l
also shows these numbers.
But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l
+ awk
trick, but I really hope there is better solution.
udev
add a comment |
Each device node under /dev
has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat
, like this:
stat -c 'major: %t minor: %T' <file>
Or, ls -l
also shows these numbers.
But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l
+ awk
trick, but I really hope there is better solution.
udev
@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!
– Dmitry Frank
Aug 23 '14 at 20:21
add a comment |
Each device node under /dev
has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat
, like this:
stat -c 'major: %t minor: %T' <file>
Or, ls -l
also shows these numbers.
But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l
+ awk
trick, but I really hope there is better solution.
udev
Each device node under /dev
has its own major/minor number pair. I know that we can retrieve this pair of numbers from the device node by means of stat
, like this:
stat -c 'major: %t minor: %T' <file>
Or, ls -l
also shows these numbers.
But how can we get device node(s) by given major and minor numbers? The only way I'm aware of is some kind of ls -l
+ awk
trick, but I really hope there is better solution.
udev
udev
asked Aug 23 '14 at 18:51
Dmitry FrankDmitry Frank
1,19861931
1,19861931
@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!
– Dmitry Frank
Aug 23 '14 at 20:21
add a comment |
@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!
– Dmitry Frank
Aug 23 '14 at 20:21
@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!
– Dmitry Frank
Aug 23 '14 at 20:21
@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!
– Dmitry Frank
Aug 23 '14 at 20:21
add a comment |
5 Answers
5
active
oldest
votes
I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.
So for example,
for file in $(find /sys/dev/ -name 7:0); do
source ${file}/uevent; echo $DEVNAME;
done;
Echoes,
loop0
vcs
Note: This was tested in Debian Wheezy
to find backwards from dev name:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
add a comment |
Not sure what you mean.
mknod foo b 8 0
Will create the device file called foo
as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev
that have the same type, major and minor, you can do (with zsh
):
For block device
8:0
:
$ zmodload zsh/stat
$ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
for char device
226:0
:
$ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
Note that anything can create files in /dev
. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc
.
On modern versions of Linux, it's usually udev
based on input from the kernel.
The name it chooses for the base device file is based on the DEVNAME
supplied by the kernel. udev
rules may change that but generally don't, and some udev
rules will add some more symlinks for convenience (like the /dev/disk/by...
ones).
You can go from major:minor to kernel DEVNAME
by looking at:
$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0
You can also get that information from the udev
database as mikeserv has shown.
add a comment |
Apparently it can be done more simply with udevadm
, and I've just found out how.
To get the DEVNAME
from udevadm
you need only do:
udevadm info -rq name $PATH
For instance, if you wanted to know the /dev
name for /sys/dev/char/5:1
you'd do:
udevadm info -rq name /sys/dev/char/5:1
OUTPUT
/dev/console
The -r
option is to specify a --root
ed path - without it the result above would read only console
. The -q
option specifies a database --query
and it takes the operand name
here - because we want the DEVNAME
.
A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:
mmdev() for d in /sys/dev/[cb]*/$1:$2
do [ -e "$d" ] || return
printf %c:%s: "${d#/*/*/}" "${d##*/}"
udevadm info -rq name "$d"
done
So running:
mmdev 8 0
prints...
b:8:0:/dev/sda
Here's the first one I wrote.
majminpath() {
set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
udevadm info --export-db |
sed 's|^[^=]*DEVNAME=||
|^[^/]|!h;/MAJOR=/N
|='"$1n.*=${2?}"'$|!d;g'
}
This just scans udevadm info --export-db
output for the matching numbers. The output looks like:
P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc
P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc
#...and so on
The workflow is like:
attempt to strip the
[^=]*DEVNAME=
string from the head of each lineif a line does not have a first character or its first character is
/
copy that line overh
old spaceif a line matches
MAJOR=
appendN
ext input line to pattern spaceif there are 2 lines in pattern space that match
=$1n.*=$2$
then copyh
old space over pattern space and auto-print; else delete pattern space
So if I do:
majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1
OUTPUT
/dev/vcsa5
/dev/sda
/dev/sda1
But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.
1
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
add a comment |
Alas, the /sys/dev
hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.
Let $M
and $m
, respectively, be the major and minor number of our device file.
Post 2.6.27 kernels
As suggested by others, the simplest approach unleashes the power of the sysfs
“virtual” file system, by chasing straight for files named $M:$m
under the folder /sys/dev
(more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent
file (in a subshell so as to prevent namespace pollution):
for file in $(find /sys/dev/ -name $M:$m)
do
(
source ${file}/uevent
echo $DEVNAME
)
done
Pre 2.6.27 kernels
Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m
throughout the /sys/block
hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev
. If /sys/block/<...>/<DEV>/dev
is one such file, then DEV
is bound to be our device's name:
dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"
add a comment |
On Linux it is possible to take advantage of certain files in /proc
virtual filesystem.
$ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions
8 1 29309568 sda1
$ grep '8:1[[:blank:]]' /proc/self/mountinfo
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered
The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f151812%2fget-device-node-by-major-minor-numbers-pair%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.
So for example,
for file in $(find /sys/dev/ -name 7:0); do
source ${file}/uevent; echo $DEVNAME;
done;
Echoes,
loop0
vcs
Note: This was tested in Debian Wheezy
to find backwards from dev name:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
add a comment |
I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.
So for example,
for file in $(find /sys/dev/ -name 7:0); do
source ${file}/uevent; echo $DEVNAME;
done;
Echoes,
loop0
vcs
Note: This was tested in Debian Wheezy
to find backwards from dev name:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
add a comment |
I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.
So for example,
for file in $(find /sys/dev/ -name 7:0); do
source ${file}/uevent; echo $DEVNAME;
done;
Echoes,
loop0
vcs
Note: This was tested in Debian Wheezy
I found a simpler approach using the sys pseudofilesystem, at /sys/dev you have the devices ordered by type an then by major/minor, the file uevent contains the device name and a bunch of other info.
So for example,
for file in $(find /sys/dev/ -name 7:0); do
source ${file}/uevent; echo $DEVNAME;
done;
Echoes,
loop0
vcs
Note: This was tested in Debian Wheezy
answered Aug 23 '14 at 21:01
xaexae
1,40376
1,40376
to find backwards from dev name:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
add a comment |
to find backwards from dev name:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
to find backwards from dev name:
for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
to find backwards from dev name:
for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
– BBK
Jan 23 '15 at 21:03
add a comment |
Not sure what you mean.
mknod foo b 8 0
Will create the device file called foo
as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev
that have the same type, major and minor, you can do (with zsh
):
For block device
8:0
:
$ zmodload zsh/stat
$ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
for char device
226:0
:
$ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
Note that anything can create files in /dev
. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc
.
On modern versions of Linux, it's usually udev
based on input from the kernel.
The name it chooses for the base device file is based on the DEVNAME
supplied by the kernel. udev
rules may change that but generally don't, and some udev
rules will add some more symlinks for convenience (like the /dev/disk/by...
ones).
You can go from major:minor to kernel DEVNAME
by looking at:
$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0
You can also get that information from the udev
database as mikeserv has shown.
add a comment |
Not sure what you mean.
mknod foo b 8 0
Will create the device file called foo
as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev
that have the same type, major and minor, you can do (with zsh
):
For block device
8:0
:
$ zmodload zsh/stat
$ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
for char device
226:0
:
$ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
Note that anything can create files in /dev
. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc
.
On modern versions of Linux, it's usually udev
based on input from the kernel.
The name it chooses for the base device file is based on the DEVNAME
supplied by the kernel. udev
rules may change that but generally don't, and some udev
rules will add some more symlinks for convenience (like the /dev/disk/by...
ones).
You can go from major:minor to kernel DEVNAME
by looking at:
$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0
You can also get that information from the udev
database as mikeserv has shown.
add a comment |
Not sure what you mean.
mknod foo b 8 0
Will create the device file called foo
as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev
that have the same type, major and minor, you can do (with zsh
):
For block device
8:0
:
$ zmodload zsh/stat
$ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
for char device
226:0
:
$ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
Note that anything can create files in /dev
. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc
.
On modern versions of Linux, it's usually udev
based on input from the kernel.
The name it chooses for the base device file is based on the DEVNAME
supplied by the kernel. udev
rules may change that but generally don't, and some udev
rules will add some more symlinks for convenience (like the /dev/disk/by...
ones).
You can go from major:minor to kernel DEVNAME
by looking at:
$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0
You can also get that information from the udev
database as mikeserv has shown.
Not sure what you mean.
mknod foo b 8 0
Will create the device file called foo
as a block device with major 8 and minor 0. If you mean to find one or any of the files in /dev
that have the same type, major and minor, you can do (with zsh
):
For block device
8:0
:
$ zmodload zsh/stat
$ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
lrwxrwxrwx 1 root root 6 Aug 23 05:28 /dev/block/8:0 -> ../sda
lrwxrwxrwx 1 root root 9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
for char device
226:0
:
$ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
lrwxrwxrwx 1 root root 12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
Note that anything can create files in /dev
. In the very old days, it was a script creating static files in there. At some point, you even had a special file system à la /proc
.
On modern versions of Linux, it's usually udev
based on input from the kernel.
The name it chooses for the base device file is based on the DEVNAME
supplied by the kernel. udev
rules may change that but generally don't, and some udev
rules will add some more symlinks for convenience (like the /dev/disk/by...
ones).
You can go from major:minor to kernel DEVNAME
by looking at:
$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0
You can also get that information from the udev
database as mikeserv has shown.
edited Aug 23 '14 at 21:27
answered Aug 23 '14 at 21:18
Stéphane ChazelasStéphane Chazelas
307k57581937
307k57581937
add a comment |
add a comment |
Apparently it can be done more simply with udevadm
, and I've just found out how.
To get the DEVNAME
from udevadm
you need only do:
udevadm info -rq name $PATH
For instance, if you wanted to know the /dev
name for /sys/dev/char/5:1
you'd do:
udevadm info -rq name /sys/dev/char/5:1
OUTPUT
/dev/console
The -r
option is to specify a --root
ed path - without it the result above would read only console
. The -q
option specifies a database --query
and it takes the operand name
here - because we want the DEVNAME
.
A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:
mmdev() for d in /sys/dev/[cb]*/$1:$2
do [ -e "$d" ] || return
printf %c:%s: "${d#/*/*/}" "${d##*/}"
udevadm info -rq name "$d"
done
So running:
mmdev 8 0
prints...
b:8:0:/dev/sda
Here's the first one I wrote.
majminpath() {
set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
udevadm info --export-db |
sed 's|^[^=]*DEVNAME=||
|^[^/]|!h;/MAJOR=/N
|='"$1n.*=${2?}"'$|!d;g'
}
This just scans udevadm info --export-db
output for the matching numbers. The output looks like:
P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc
P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc
#...and so on
The workflow is like:
attempt to strip the
[^=]*DEVNAME=
string from the head of each lineif a line does not have a first character or its first character is
/
copy that line overh
old spaceif a line matches
MAJOR=
appendN
ext input line to pattern spaceif there are 2 lines in pattern space that match
=$1n.*=$2$
then copyh
old space over pattern space and auto-print; else delete pattern space
So if I do:
majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1
OUTPUT
/dev/vcsa5
/dev/sda
/dev/sda1
But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.
1
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
add a comment |
Apparently it can be done more simply with udevadm
, and I've just found out how.
To get the DEVNAME
from udevadm
you need only do:
udevadm info -rq name $PATH
For instance, if you wanted to know the /dev
name for /sys/dev/char/5:1
you'd do:
udevadm info -rq name /sys/dev/char/5:1
OUTPUT
/dev/console
The -r
option is to specify a --root
ed path - without it the result above would read only console
. The -q
option specifies a database --query
and it takes the operand name
here - because we want the DEVNAME
.
A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:
mmdev() for d in /sys/dev/[cb]*/$1:$2
do [ -e "$d" ] || return
printf %c:%s: "${d#/*/*/}" "${d##*/}"
udevadm info -rq name "$d"
done
So running:
mmdev 8 0
prints...
b:8:0:/dev/sda
Here's the first one I wrote.
majminpath() {
set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
udevadm info --export-db |
sed 's|^[^=]*DEVNAME=||
|^[^/]|!h;/MAJOR=/N
|='"$1n.*=${2?}"'$|!d;g'
}
This just scans udevadm info --export-db
output for the matching numbers. The output looks like:
P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc
P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc
#...and so on
The workflow is like:
attempt to strip the
[^=]*DEVNAME=
string from the head of each lineif a line does not have a first character or its first character is
/
copy that line overh
old spaceif a line matches
MAJOR=
appendN
ext input line to pattern spaceif there are 2 lines in pattern space that match
=$1n.*=$2$
then copyh
old space over pattern space and auto-print; else delete pattern space
So if I do:
majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1
OUTPUT
/dev/vcsa5
/dev/sda
/dev/sda1
But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.
1
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
add a comment |
Apparently it can be done more simply with udevadm
, and I've just found out how.
To get the DEVNAME
from udevadm
you need only do:
udevadm info -rq name $PATH
For instance, if you wanted to know the /dev
name for /sys/dev/char/5:1
you'd do:
udevadm info -rq name /sys/dev/char/5:1
OUTPUT
/dev/console
The -r
option is to specify a --root
ed path - without it the result above would read only console
. The -q
option specifies a database --query
and it takes the operand name
here - because we want the DEVNAME
.
A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:
mmdev() for d in /sys/dev/[cb]*/$1:$2
do [ -e "$d" ] || return
printf %c:%s: "${d#/*/*/}" "${d##*/}"
udevadm info -rq name "$d"
done
So running:
mmdev 8 0
prints...
b:8:0:/dev/sda
Here's the first one I wrote.
majminpath() {
set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
udevadm info --export-db |
sed 's|^[^=]*DEVNAME=||
|^[^/]|!h;/MAJOR=/N
|='"$1n.*=${2?}"'$|!d;g'
}
This just scans udevadm info --export-db
output for the matching numbers. The output looks like:
P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc
P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc
#...and so on
The workflow is like:
attempt to strip the
[^=]*DEVNAME=
string from the head of each lineif a line does not have a first character or its first character is
/
copy that line overh
old spaceif a line matches
MAJOR=
appendN
ext input line to pattern spaceif there are 2 lines in pattern space that match
=$1n.*=$2$
then copyh
old space over pattern space and auto-print; else delete pattern space
So if I do:
majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1
OUTPUT
/dev/vcsa5
/dev/sda
/dev/sda1
But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.
Apparently it can be done more simply with udevadm
, and I've just found out how.
To get the DEVNAME
from udevadm
you need only do:
udevadm info -rq name $PATH
For instance, if you wanted to know the /dev
name for /sys/dev/char/5:1
you'd do:
udevadm info -rq name /sys/dev/char/5:1
OUTPUT
/dev/console
The -r
option is to specify a --root
ed path - without it the result above would read only console
. The -q
option specifies a database --query
and it takes the operand name
here - because we want the DEVNAME
.
A very simple means of finding the path to a char and/or block device given only the major:minor numbers might look like:
mmdev() for d in /sys/dev/[cb]*/$1:$2
do [ -e "$d" ] || return
printf %c:%s: "${d#/*/*/}" "${d##*/}"
udevadm info -rq name "$d"
done
So running:
mmdev 8 0
prints...
b:8:0:/dev/sda
Here's the first one I wrote.
majminpath() {
set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
udevadm info --export-db |
sed 's|^[^=]*DEVNAME=||
|^[^/]|!h;/MAJOR=/N
|='"$1n.*=${2?}"'$|!d;g'
}
This just scans udevadm info --export-db
output for the matching numbers. The output looks like:
P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc
P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc
#...and so on
The workflow is like:
attempt to strip the
[^=]*DEVNAME=
string from the head of each lineif a line does not have a first character or its first character is
/
copy that line overh
old spaceif a line matches
MAJOR=
appendN
ext input line to pattern spaceif there are 2 lines in pattern space that match
=$1n.*=$2$
then copyh
old space over pattern space and auto-print; else delete pattern space
So if I do:
majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1
OUTPUT
/dev/vcsa5
/dev/sda
/dev/sda1
But, as @xae points out, block/char type devices can share maj:min combinations, and so this might possibly print more than one path per call.
edited Mar 11 '16 at 22:16
ckujau
1,207612
1,207612
answered Aug 23 '14 at 19:35
mikeservmikeserv
45.7k668159
45.7k668159
1
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
add a comment |
1
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
1
1
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
Unfortunately it's no so easy, a block and a character device can share the same major number. Take a look at the file /proc/devices.
– xae
Aug 23 '14 at 19:55
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
I gotta check subsystem - that's right. Thanks, @xae.
– mikeserv
Aug 23 '14 at 20:03
add a comment |
Alas, the /sys/dev
hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.
Let $M
and $m
, respectively, be the major and minor number of our device file.
Post 2.6.27 kernels
As suggested by others, the simplest approach unleashes the power of the sysfs
“virtual” file system, by chasing straight for files named $M:$m
under the folder /sys/dev
(more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent
file (in a subshell so as to prevent namespace pollution):
for file in $(find /sys/dev/ -name $M:$m)
do
(
source ${file}/uevent
echo $DEVNAME
)
done
Pre 2.6.27 kernels
Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m
throughout the /sys/block
hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev
. If /sys/block/<...>/<DEV>/dev
is one such file, then DEV
is bound to be our device's name:
dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"
add a comment |
Alas, the /sys/dev
hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.
Let $M
and $m
, respectively, be the major and minor number of our device file.
Post 2.6.27 kernels
As suggested by others, the simplest approach unleashes the power of the sysfs
“virtual” file system, by chasing straight for files named $M:$m
under the folder /sys/dev
(more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent
file (in a subshell so as to prevent namespace pollution):
for file in $(find /sys/dev/ -name $M:$m)
do
(
source ${file}/uevent
echo $DEVNAME
)
done
Pre 2.6.27 kernels
Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m
throughout the /sys/block
hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev
. If /sys/block/<...>/<DEV>/dev
is one such file, then DEV
is bound to be our device's name:
dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"
add a comment |
Alas, the /sys/dev
hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.
Let $M
and $m
, respectively, be the major and minor number of our device file.
Post 2.6.27 kernels
As suggested by others, the simplest approach unleashes the power of the sysfs
“virtual” file system, by chasing straight for files named $M:$m
under the folder /sys/dev
(more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent
file (in a subshell so as to prevent namespace pollution):
for file in $(find /sys/dev/ -name $M:$m)
do
(
source ${file}/uevent
echo $DEVNAME
)
done
Pre 2.6.27 kernels
Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m
throughout the /sys/block
hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev
. If /sys/block/<...>/<DEV>/dev
is one such file, then DEV
is bound to be our device's name:
dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"
Alas, the /sys/dev
hierachy was only added to the kernel as late as 2.6.27 (cf. the relevant commit against the kernel codebase), so we need a “bifurcated” approach.
Let $M
and $m
, respectively, be the major and minor number of our device file.
Post 2.6.27 kernels
As suggested by others, the simplest approach unleashes the power of the sysfs
“virtual” file system, by chasing straight for files named $M:$m
under the folder /sys/dev
(more than one file is to be expected if we don't know whether our device is a character- or a block-based one), and then sourcing the uevent
file (in a subshell so as to prevent namespace pollution):
for file in $(find /sys/dev/ -name $M:$m)
do
(
source ${file}/uevent
echo $DEVNAME
)
done
Pre 2.6.27 kernels
Let us assume, for simplicity's sake, that our file is a block device (a similar approach applies for character devices). We will search for the string $M:$m
throughout the /sys/block
hierarchy, by examining (underneath that folder) the contents of every file whose name happens to be dev
. If /sys/block/<...>/<DEV>/dev
is one such file, then DEV
is bound to be our device's name:
dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"
answered Oct 16 '15 at 3:53
Roberto RealeRoberto Reale
1112
1112
add a comment |
add a comment |
On Linux it is possible to take advantage of certain files in /proc
virtual filesystem.
$ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions
8 1 29309568 sda1
$ grep '8:1[[:blank:]]' /proc/self/mountinfo
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered
The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.
add a comment |
On Linux it is possible to take advantage of certain files in /proc
virtual filesystem.
$ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions
8 1 29309568 sda1
$ grep '8:1[[:blank:]]' /proc/self/mountinfo
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered
The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.
add a comment |
On Linux it is possible to take advantage of certain files in /proc
virtual filesystem.
$ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions
8 1 29309568 sda1
$ grep '8:1[[:blank:]]' /proc/self/mountinfo
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered
The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.
On Linux it is possible to take advantage of certain files in /proc
virtual filesystem.
$ grep '8[[:blank:]]+1[[:blank:]]+' /proc/partitions
8 1 29309568 sda1
$ grep '8:1[[:blank:]]' /proc/self/mountinfo
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered
The simple form of the pattern already provides information about the desired device in the output, however additional filtering to extract just one particular string is possible as well.
answered 4 hours ago
Sergiy KolodyazhnyySergiy Kolodyazhnyy
10.4k42663
10.4k42663
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f151812%2fget-device-node-by-major-minor-numbers-pair%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
@mikeserv, yes I know that some devices can share these numbers, so in my initial question I've mentioned: "get device node(s)". Ideally I want to get a list with all device nodes whose major/minor numbers match, one node per line. That's strange we don't have a ready tool for that. Thanks for the answer btw!
– Dmitry Frank
Aug 23 '14 at 20:21