[solved] udev rule not starting gpsd during boot
I'm trying to configure gpsd 2.96 to start automatically from udev rule on a Slack 13.37 box.
1. I've compiled and installed gpsd from sources and made sure it starts manually. 2. I've copied the /lib/udev/gpsd.hotplug and /lib/udev/gpsd.hotplug.wrapper scripts in their places from the source tree and made them executable. 3. I've copied the gpsd.rules file from sources into /etc/udev/rules.d 4. I renamed it 99-persistent-gpsd.rules to run late in the bootup process. 5. I've copied the /etc/default/gpsd file from sources and made sure it has the right settings inside. Now, for the results. If I plug the gps usb dongle in while the system runs, it starts gpsd if it is not started, and it connects to it just as it should. But if I start the system with the dongle in, gpsd doesn't get started during boot. I can't find any relevant message in /var/log/syslog or /var/log/messages for boot time. There is stuff there from when I plug the dongle in while the system is running though. It's like udev ignores the rules for it at boot time. Is there something in the Slackware boot scripts that would prevent running those scripts (/lib/udev/gpsd.hotplug.wrapper which in turn runs /lib/udev/gpsd.hotplug which is a Python script)? Here is the contents of 99-persistent-gpsd.rules (ignore the comments referring to Debian, it was meant for a Debian box). My usb gps adapter is the first one - the Prolific chipset one: Code:
# udev rules for gpsd Thank you |
There is a slackbuild available for gpsd on slackbuilds.org, see http://slackbuilds.org/repository/13.37/system/gpsd/
Not sure it will answer you question -- but at least it can help you keep your system clean ;) |
Thanks for the reply. I've actually used the slackBuilds script - just modified it to use version 2.96 instead of 2.95. The slackBuilds script does not install or configure any of the udev rules. I had to copy them manually from the source code. If I manage to get it going, I would like to go back to slackBuilds and suggest they modify their script to automatically configure the udev stuff.
As a follow-up to my post above - I know that the rule gets triggered during boot - because gps0 shows up in /dev - otherwise it would be just ttyUSB0. I just can't figure out why the RUN script doesn't get run. Sebastian |
I'm pretty sure the SBo gpsd won't help with the udev problem -- it doesn't even try to do anything with udev rules. So thanks to xj25vm for poking it with a stick :)
I'll do some experiments this afternoon, and if we end up with success, I'll try to include some optional support for udev in the SBo SlackBuild -- even if it's just a new paragraph in the README. (Niels Horn just approved an update for version 2.96, so apologies to Niels if we change it again in the near future!) |
It seems there is a problem with the udev setup - either in general, or the way it is configured in Slackware. I can't run anything from a udev rule. I've tried the following simple setup which is supposed to write a simple file in /var/run during boot if the gps dongle is connected:
Code:
#/etc/udev/ruled.s/99-gpsd.rules Code:
#!/bin/bash I don't think we stand a chance of getting the gpsd started automatically by udev during boot if the RUN argument doesn't work (although, bizarrely, it works fine if the computer is booted/running and the usb gps dongle is inserted). Sebastian |
Well, I think I know what's going on here, and it isn't pretty.
gpsd insists on having a control socket at /var/run/gpsd.sock (even if you set the relevant variable in /etc/default/gpsd to a null string). Unfortunately, neither gpsd nor /lib/udev/gpsd.hotplug can create this socket when /etc/rc.d/rc.udev is doing its coldplug thing, because the root filesystem is still read-only at this point in the boot. (Digression: you can see this happening if you dial up udev's log level and ctrl-s the display at just the right point. Code:
udevd-work[1057]: '/etc/udev/gpsd-hotplug-wrapper' started Note also, that despite the above failure, the other part of the udev rule -- creating the extra device symlink /dev/gpsN -- actually works ok. Maybe there would be a happy ending if only gpsd.hotplug and gpsd.hotplug.wrapper exited with an error code having failed to create the socket. Then, when Slackware later invokes udevadm trigger --type=failed, the scripts would run again, and would succeed. (This stuff is complicated. Am I getting it right?!) Alas, this does not happen. The reason why it doesn't or can't return an error code might be the unrelated situation that's described in the comments in gpsd.hotplug Quote:
The best fix for booting would be to edit rc.local so that it starts gpsd if /dev/gps0 exists. You can leave everything else exactly the way it is now so that hotplug will also work. |
Here's a scrippet that might help.
Code:
while true |
Hi 55020,
I think I followed pretty much all your explanation. Thank you for that - I didn't realise the first pass of udev is done while the root filesystem is in read-only mode. I am on the gpsd mailing list - and I will try to see if there is any interest in modifying the two hotplug scripts to return a non-zero value in case of failure. The problem with starting gpsd from rc.local (which I have considered) is that once the boot is out of the way, I will end up with a running gpsd, but not with a usb gps adapter connected to it - if it was plugged in before the computer is started. That is because the hotplug script sends commands to the gpsd daemon through the socket to connect to the gps device. That unless I start gpsd with the device name (/dev/ttyUSB0) on the command line. This relies on the gps dongle being assigned the same device name everytime - which might just work in my particular setup. It's just not that elegant as the hotplug. |
I'm trying to modify the gpsd.hotplug.wrapper script to return a failure message if it can't write to the filesystem - so that it get's re-run after the filesystem is mounted rw.
I'm experimenting with a very simple script like this: Code:
#!/bin/bash Code:
What does it take to register a rule as failed with udev - so that it gets re-run later on? I was thinking an exit code of 1 for a bash script should have been enough. I've read the man page for udev and udevadm - but they don't seem to say how exactly to fail a rule. Sebastian P.S. - Sorry for being a bit OT here - but I thought I better keep all the conversation belonging to the gpsd and udev problem in one place. |
Quote:
The udev rules supplied by gpsd are neither elegant nor foolproof; they assume that more or less any serial USB converter is a GPS. I use the exact same serial cable with an eTrex and at other times with various scientific data loggers, and additionally I've got a diabetes blood glucose meter with the exact same PL2303 USB id. There is no way that udev can distinguish these use cases. And that's why I don't use gpsd hotplug. It doesn't fit my lifestyle :cool: but YMMV... |
I have used gpsd with manual start for almost two years now on my own laptop - and I would have kept on using it. But I'm currently working on a vehicle onboard tracking system, using Slack and gpsd - and that's when I stumbled over this whole $£%^$ - erm, extra complication. This computer will be physically locked in its case, will start automatically when the engine starts - so it needs a reliable way of starting gpsd without any intervention. I will probably stick with doing "gpsd -n /dev/ttyUSB0" from rc.local - and this will fit my use case this time.
I would have loved it, however, if I could have come up with a more flexible script to do things properly, from udev - which would have worked well on Slackware - so that it can be added to the SBo repository. Well, I suppose you win some, you lose some :-) . In retrospect, gpsd should really include the option to scan for usb devices itself when it starts and add the right ones automatically to it's pool. This way a gpsd startup script just doing "gpsd --watch-usb" or something similar would have been enough. At worst, a udev rule including "gpsd --rescan" to tell gpsd when to have another look for new devices should cover all situations. At least I think that would have been the neatest way. |
How about leaving 99-persistent-gpsd.rules in place, and putting this in /etc/rc.local
Code:
if [ -l /dev/gps0 -a -x /lib/udev/gpsd-hotplug ]; then Meanwhile, to answer your earlier question: "What does it take to register a rule as failed with udev - so that it gets re-run later on?" -- apparently this is the magic invocation (but I had to look it up, and haven't tried it). Code:
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", RUN{fail_event_on_error}="/lib/udev/gpsd.test" |
Thank you for that. In that case, I wonder if we can suggest two modifications to the gpsd team:
1. Modify their existing udev rule file to add "{fail_event_on_error}" for every line of the file. 2. Modify the gpsd.hotplug.wrapper script to include a test along the lines: Code:
This way, the gpsd.hotplug.wrapper should fail on the first udev run, and should succeed on the second run. Wouldn't the two modifications above make the upstream setup fully compatible with Slackware (in theory - I haven't tried it yet)? - while keeping it compatible with the other distros as well. I really would like if that would be the case, instead of having some modifications which only apply to one distribution. It would also be easier to package. |
I've just tried the {fail_event_on_error} option and it seems to do nothing. It runs the script on the first pass of udev (and fails to write the file to /var/run), but doesn't run it on the second pass.
|
1 Attachment(s)
OK - I think I have a compromise solution to suggest for the SBo repository. I've built an rc.gpsd script to go in /etc/rc.d and be triggered from rc.local. This will:
1. Start gpsd 2. Pass ttyUSB0 (or any other device) on the command line, in case the usb dongle was already plugged in when the computer booted. 3. Also pass -F /var/run/gpsd.sock option on the command line, so that the gpsd daemon can be interracted with by gpsctl through udev, and receive any new device plugged in after the computer boots. In conjunction with using /udev/lib/gpsd.hotplug, /udev/lib/gpsd.hotplug.wrapper, gpsd.rules (maybe renamed /etc/udev/rules.d/99-persistent-gpsd.rules to fit what seems to be Slackware naming style) - this should cover most use cases, of having the device plugged in when the computer starts, and plugging it in later. I attach the rc.gpsd here (remove .txt from the end). The other files are in the gpsd sources. What do you think? |
Yes, the general approach sounds good and I've grabbed a copy of your rc script. It's too late for the 2.96 update, which has already been approved, but I'll definitely include this with the SBo SlackBuild next time, though it probably won't be fully enabled by default, to avoid surprises for people upgrading. gpsd 3.0 will be a big update anyway, as it's going over to cmake -- I already have an early draft and I'll update it and put it on github in the very near future.
As I said before, thanks for poking this with a pointy stick. It's been on my TODO list (near the bottom, just above "do proper backups") for a very long time and you've helped a lot :cool: |
I am the one who should thank you for answering my questions, throwing in ideas and generally for any work you do for SBo. As a slacker, I find it very useful.
I've sent an email to both the gpsd-users and gpsd-dev lists suggesting that they might consider moving to a standard /etc/gpsd.conf file, with [global] and [device_name] type sections, based on serial number of devices (as hardware id's are unreliable for gps devices), and a gpsdconf command line wizard which can be run every time a new usb adapter is used for the first time - which would update gpsd.conf with the correct serial number, and any options the user might wish for that adapter. The whole process would be akin to pairing up with a gpsd adapter/receiver - the way bluetooth devices get paired up the first time they connect. This way, gpsd could use inotify (or something else) to know when a new ttyUSBx or ttySx device is plugged in, and if the serial number is in gpsd.conf, it would connect to it automatically. No more udev, no more gpsd.hotplug and gpsd.hotplug.wrapper and the rest of the complication. All would one do is start the gpsd binary on system startup, and be done with it. In my mind, this would be a wonderfully simplified system - but I'm not holding my breath over it getting any traction. I could have equally missed something important in my grand scheming anyway :-) I'll mark this thread as solved now - as I think it is as solved as it will ever get considering all factors involved. Thanks again for all your help. P.S. Here is my idea of a /etc/gpsd.conf file: Code:
|
1 Attachment(s)
I'm attaching a modified version of the rc.gpsd script as I've discovered two bugs in the previous version. I've also added some comments at the top to explain why this script is necessary under Slackware. I'm hoping 55020 you are still monitoring this thread.
|
Hi Sebastian, have a look at http://github.com/idlemoor/SBo-fork/...edingEdge/gpsd which I have been working on for a while -- this is a experimental preview of what will become the SBo SlackBuild when gpsd-3.0 is released. It now includes your new rc.gpsd, revised somewhat. Among the changes, it uses /dev/gps0 instead of /dev/ttyUSB0 (thus allowing coexistence of a GPS with any other USB serial devices, if they are distinguishable to udev). This isn't enabled by default. Read the README.
The README also points out that there is now a dependency on scons, which is available from SBo. Before building gpsd, you'll need to make a tarball from the gpsd project's git repository. If you're comfortable doing that, fine, otherwise you can use the repo2tarball script I've been hacking lately, which is in a parallel subdirectory in the BleedingEdge section of my github. This will clone/pull from the remote git repo, and create a tarball named something like gpsd-master.6bf5d9e.tar.gz. You then build gpsd from this tarball and install/upgrade the package as usual: Code:
repo2tarball gpsd |
I've had a look at github and I like the look of things. One minor suggestion. If it would be me, I would keep all the options inside rc.gpsd - and keep the part that goes into rc.local as minimal as possible. So in rc.local I'd put something like:
Code:
if [ -x /etc/rc.d/rc.gpsd ]; then Code:
if [ ! -e $GPSD_DEVICE ]; then I like your "GPSD_SOCKARG" idea - I couldn't think of a suitable name for that variable. |
Will do. In particular, you're right about the device name and it makes mincemeat of the bogus reason why I did it that way. Ta!
|
I was just looking at the udev rule supplied by the gpsd team. I just realised that, if several usb-to-serial devices are plugged in (not necessarily all gps receivers) - there is no guarantee that the gps receiver will end up under /dev/gps0. They use "SYMLINK+="gps%n" which I believe means that it will take the same number assigned by the kernel to /dev/ttyUSBx which is linking to. There could be only one gps receiver plugged (next to other usb-to-serial devices) and still end up as /dev/gps3 or /dev/gps4. And no way to control this with the current settings. In the light of this, the way I see it there are two options:
1. Modify the udev rule and recommendation, so that people hardwire their own device number e.g. instead of using "SYMLINK+="gps%n" use "SYMLINK+=gps0". 2. Or, modify rc.gpsd, by removing GPSD_DEVICE variable, and instead do something like "ls /dev/gps*", check if anything comes out of that, and if yes, for first device found start gpsd on it. That of course makes the willing assumption there is only one gps receiver plugged in when the computer starts, and/or ignores any other. Otherwise we would deal with a situation where rc.gpsd relies on the chance that the gps receiver is the first one to be polled by udev of any serial-to-usb devices connected - which, I would think, is very flimsy. It also pretty much ruins one of the main purposes of using udev for this - which, I believe, was to deal with having several usb-to-serial devices plugged in. Unless I'm misunderstanding the udev rules. |
I worked a bit on the latest version of rc.gpsd and I adapted it to cope with /dev/gpsx devices numbered in an unpredictable fashion. Also, I adapted it to cope with an unknown number of gps devices plugged in when the computer starts. I know this is somewhat unlikely - but I think this way it is more flexible and robust. If you think this is overkill, it could be changed to just start gpsd on the first device encountered. Here is the part of it I've modified:
Code:
|
Sorry for using this thread to conduct a dialogue of diminishing public interest, but I've just pushed a new set of gpsd files to Github, including fixes for the device numbering issue Sebastian pointed out, the config issue, and patches for a number of ghastly upstream problems.
There is now a config file at /etc/rc.d/rc.gpsd.conf, which is where it should be in any distro of good taste and discernment ;) I might try to do an LQ Blog about this, so that we have somewhere else to discuss any matters arising. |
All times are GMT -5. The time now is 05:06 PM. |