Any experience with run levels in linux and daemons?

Hi all,

Im having some problems using serial communication to my arduino from a daemon Ive written in perl running from init.d on a ubuntu box.

This is a headless server running the cctv system zoneminder.
The arduino is going in a switch box connected to the server by usb cable so the Scout leaders at the hut the cctv is covering can turn it on and off without having to touch a keyboard.

The daemon communicates over serial/usb to the arduino that has a key switch and a couple of status led's.
Ive set the daemon running under level 3 and above in the init.d bash script but im getting no response from the arduino script over serial.

If I run the perl script/daemon from the command line it works perfectly.
But not if I start it as a service via "service zoneswitch start".
So its something to do with init.d and the permissions/runlevels the perlscript/daemon is running under.

So Im wondering if anyone has any experience with daemons under linux, run levels and serial/usb and maybe can give me a pointer or two.
I can post the code but its a bit on the long side so Ill wait till someone requests it if it will be a help.

Thanks

Gordon

Have you tried executing the script in this file?
/etc/rc.local
It is executed after all multiuser startups.

I could give it a try, but I'd prefer to have it run from inet.d.
Ive posted on perl monks as well.
Ill keep plugging away.

Gordon

Please clarify what works and what doesn't. The actual perl script/daemon works when you run it in a terminal? The init script doesn't work when you try to start it using "service zoneswitch start", but what happens if you try to run the init script directly, i.e., "/etc/init.d/zoneswitch start"? Do you get any error messages or does it fail silently? You could also post the init script and the perl code here.

Thanks for looking.

Good point running the bash init script directly, "/etc/init.d/zoneswitch start".
Dont know why I hadnt thought of that. I might get more of an idea of whats happening.

I can run the perl script directly, everything works as expected.

Run it through "service zoneswitch start". Daemon starts and stays started. I get all the debug info through syslog as expected but nothing goes over the serial/usb link to the arduino.

Ill give "/etc/init.d/zoneswitch start" a go and see what I get then. Maybe Ill see some errors or warnings this way.

Ive posted all the code on perl monks so rather than cluttering here up, it can be seen here:http://www.perlmonks.org/?node_id=973357

Gordon

I don't think that running "/etc/init.d/zoneswitch start" will show you any more error messages than "service zoneswitch start" because Proc::Daemon::Init in the perl script detaches stdout/stderr from the terminal. You could of course try to comment out Proc::Daemon::Init and see if it then shows some warnings.

I didn't see anything obviously wrong in the perl script. Do you know where exactly serial communication fails? Does it fail at the initialization/connection phase or when you try to write in the /dev/ttyUSB0? It may be easier to debug if you write a minimal version of the script that only initializes the serial port and writes to it. Try to catch all error messages and log them to syslog. If the script seem to silently die at some point, add the suspicious lines within an eval block and log the error message, e.g:

eval {
   $port = Device::SerialPort->new($portPath);
};
if ($@) {
    syslog(LOG_ERR, "Device::SerialPort->new failed: $@");
}

Btw, are you logged in as the same user (root?) when you run the perl script directly and when you try to execute is a service? What are the permissions/owner of /dev/ttyUSB0?

Got there in the end. Several things caught me out.

First, dirty test environment. I wasnt making sure that any processes started during testing were killed. Stupid mistake by me caused some confusion while trying to work out what was happening. Of course this shouldnt be able to happen if the pid files worked correctly. see Second point.

Second, pid files part 1, The skeleton bash script in init.d doesnt make it clear that pid files arnt created by start-stop-daemon when you give it the path to the pid file. You have to make sure that you set --make-pidfile to create the pid file or it assumes your service/daemon creates the pid file.

Third, pid files part 2, When start-stop-daemon is called with --make-pidfile, it doesnt know anything about any forking within your service/script. It creates the pid file with the pid before forking. So any further calls of start-stop-daemon wont work as the pid file is not associated with the forked process.

As I said got there in the end, just need to put the logic into my perl service/daemon to handle the pid file and locking rather than relying on the init.d script and start-stop-daemon as I assumed you could. Hopefully if someone else tries something like this, the above will help

Gordon