LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 09-24-2010, 01:11 PM   #1
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,551
Blog Entries: 28

Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
udev rules - how to pass ATTRS{*} values to the RUN command?


Hello :-)

I'm modifying a working udev rule which runs a script that mounts a USB HDD and synchronises files to it.

The USB HDDs have been troublesome, losing many files and even losing file systems a couple of times. To investigate, I want to log the USB HDD product name and serial number so would like to pass ATTRS{product} and ATTRS{serial} values to the script.

This may not be possible; I cannot see anything about how to do it in either the udev man page nor Daniel Drake's "Writing udev rules" Version 0.74 but it seems such an obvious thing to want to do, I'm wondering if I've overlooked something.

udev is version 141 and the OS is Slackware 13.0 32-bit.

Best

Charles
 
Old 09-24-2010, 02:00 PM   #2
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
passing udev RUN arguments to external program

Hi catkin,

As per the udev manpage, the RUN+= thingy takes a printf-like syntax, which took me a few whiles to figure out. But, here's an example of what you want.

First, my rule (broken for readability):
Code:
SUBSYSTEMS=="usb",ATTRS{manufacturer}=="Kingston",ATTRS{product}=="DataTraveler 2.0",
NAME{all_partitions}="usb-kingston",GROUP="plugdev",
RUN+="/home/sasha/udevtest.sh %M %m %s{manufacturer}",$major,$minor,$attr{manufacturer}
Here's what the udevtest.sh program contains:
Code:
#!/bin/bash

echo >> /home/sasha/udevtest.out
echo "Major is: $1" >> /home/sasha/udevtest.out
echo "Minor is: $2" >>  /home/sasha/udevtest.out
echo "ATTR{manufacturer} is: $3" >>  /home/sasha/udevtest.out

exit 0
and here's the output resulting from me plugging the USB device into the machine:
Code:
sasha@reactor: tail -f udevtest.out

Major is: 189
Minor is: 18
ATTR{manufacturer} is: Kingston

Major is: 21
Minor is: 5
ATTR{manufacturer} is: 

Major is: 254
Minor is: 5
ATTR{manufacturer} is: 

Major is: 8
Minor is: 64
ATTR{manufacturer} is:
Notice that there are more than one event generated above, thus the script is called more than once, but only one of the calls to the script actually had the $attr variable available to it.. So, you will probably want to have a more specific rule than the example I used, and/or maybe target your rule differently so that it only executes the script once. Or, make your script have some sanity checking to ensure that it has been given enough parameters to run to completion correctly. I'll leave that fiddling up to you to decide, but if I can help further, I'll try!

Good luck!

Oh, and for debugging, you'll want to do one of several things. I do it this way:

- edit my rule.
- make sure the device is unplugged
- /etc/rc.d/rc.udev reload
- connect device to test your rule.
- repeat

..because if the device is still plugged in, reloading the rules doesn't seem sometimes to actually reload. To be sure, I remove the device first.

And if you need/want, read about `udevadm` and its "monitor" command, for if you want to watch the udev events going by on your screen.
 
1 members found this post helpful.
Old 09-25-2010, 07:25 AM   #3
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,551
Blog Entries: 28

Original Poster
Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
Hello Sasha

Many thanks for your research and your answer; I would have been stuck without it.

The key information was that the value of ATTRS{<whatever>} is represented by $attr{<whatever>} not $attrs{<whatever>}. After finding this solution I did not explore capitalisation, that is $ATTR{<whatever>}.

As for the "simple printf-like string substitutions" of the udev man page, the accent should be on simple rather than printf-like! Experimentation showed that the %* tokens that do look like printf "conversion specifications" (because they begin with a %) do not work as conversion specifications but as synonyms. An example may make that clearer. I found that using $major was functionally equivalent to your use of %M.

So what is printf-like? Perhaps only that %% must be used to get a % character (and $$ to get a $ character) and that length may be specified. As it say on the man page, "The count of characters to be substituted may be limited by specifying the format length value. For example, %3s{file} will only insert the first three characters of the sysfs attribute". I did not explore this, nor whether it works with the $* tokens as well as the %* tokens.

And what is not printf-like? The usage is not 'format string', value1, value2, . Only the format string is required and it includes the required values. Here's the RUN+= I ended up with.
Code:
 RUN+="/lib/udev/local/usb_hdd_for_bacula_sync.sh -d $major $minor '$attr{product}' '$attr{serial}'"
The single quotes were needed in case the product or serial values had embedded whitespace.

If I have understood correctly, your code should work identically without the ",$major,$minor,$attr{manufacturer}"

Best

Charles
 
1 members found this post helpful.
Old 09-25-2010, 07:49 AM   #4
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Hey there

Glad you got a working solution. And, I agree - the manpage, for one thing, doesn't really go out of its way to explain this "printf-like" thing they describe -- AND the printf-ness they describe is not as printf-like as we might be used to. It does resemble printf though. A couple examples in the man-page would be welcome.

Until your thread/question, I had never had reason to look into this before (passing attrs along to another program from udev), but it looked like a good opportunity to try/learn something else about udev - and I did. And you improved on that with your final RUN+= statement by showing that the %M parts aren't needed, unless maybe one wants that length-limiting or similar, such as %3s{file}. Otherwise just inserting the variables directly into the string should work. I now believe I mis-interpreted the man-page, and incorrectly thought that both the %X and the $xyz were required to produce a given attr in the output (i.e. the %x would be replaced with the $xyz) when in fact, it appears the two are interchangeable. And that said, I wonder now why my rule worked at all!

It looks like you were on the right track already and just needed the $attrs changed to $attr. But, I can remember some time ago when the man-page said to use ATTR in the matching rules themselves, but in reality, ATTRS was what worked (maybe a bug/oversight??).

Compared to say, basic scripting for example, which you/I could throw something together and be pretty confident it will basically work, udev rules are always (for me at least) something that one can't just write and save the file and expect it to work; the rules need to be tested to make sure not only that we created a syntactically correct rule, but that the syntax that worked on udev version $ABC is still the right syntax for udev version $TODAY. It's that moving target thing.

Thanks for your feedback. Later on today, I plan to do a little more testing on this, so may post a few variations of the RUN+= thing to compare %X to $XYZ to see what works (and what doesn't).

Cheerios
 
Old 09-25-2010, 07:53 AM   #5
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
P.S. -

Quote:
And what is not printf-like? The usage is not 'format string', value1, value2, … . Only the format string is required and it includes the required values. Here's the RUN+= I ended up with.
I'm not big into C programming, but I seem to recall, maybe wrongly, seeing strings printed in C by doing something like:
Code:
printf ("Hello there %s, my name is %s.\n",name1,name2)
So that's what led me down the path I took.
 
Old 09-25-2010, 02:54 PM   #6
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,551
Blog Entries: 28

Original Poster
Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
Yes, I vaguely recall something like that and, given the man page's "printf-like", I thought you had got it; only experimentation revealed something different.
 
Old 09-25-2010, 04:30 PM   #7
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Well I have tried a dozen or so different printf-like ways of writing the RUN statement, and no way no how can I make anything occur other than a standard substitution; %x works identically to $xyzzz, i.e. the % method and the $ method both work, and both produce the same result. Formatting, such as the '%3s{file}', does not work.

I have noted that my (udev version 153) manpage for `udev` does not have that final piece:
Quote:
The count of characters to be substituted may be limited by specifying the format length value. For example, '%3s{file}' will only insert the first three characters of the sysfs attribute.
I quoted the above from http://linux.die.net/man/7/udev but I see no version number there, nor a revision date on the page.
 
Old 09-26-2010, 01:28 AM   #8
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,551
Blog Entries: 28

Original Poster
Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
It might be a typo in the man page; %s3<whatever> would be more printf-like.
 
Old 09-26-2010, 05:43 AM   #9
GrapefruiTgirl
Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
I did try mixing it up as you suggested; still no go. Either way I get a literal string of the %??{file}.

A 'typo' is possible, but I feel it isn't a typo since the entire clause is not there; I figure it was removed. It *might* (still?) work in your version of udev though, if/since it is present in your man-page.

Oh well - either way, you got your bit working now; and fiddling with this has learned me a couple new little things about udev rules, and was a good refresher/update opportunity: my udev tends to go un-fiddled-with until something stops working in some new version-- and the research begins to figure out what has changed

Best regards,
Sasha
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to edit "/etc/udev/rules.d/40-basic-permissions.rules" file cygan Linux - Newbie 11 03-09-2009 05:22 AM
cat: /etc/udev/rules.d/70-persistent-net.rules: No such file or directory rcg1984 Linux From Scratch 2 09-17-2008 07:02 AM
pass arguments and return values from a function in UNIX gaynut Programming 4 07-10-2008 01:56 AM
slackware-current, udev 0.96, and custom udev rules not working rignes Slackware 6 08-10-2006 03:43 AM
need help fixing my udev rules or ivman rules hedpe Linux - Hardware 2 03-18-2006 10:07 AM


All times are GMT -5. The time now is 09:31 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration