Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm currently running a server console program in a screen because I need to both read it and occasionally send commands.

I'd like to run the app as a deamon in the background (start/stop it with init).

I could tail -f the log, but that won't let me send input to the process.

Is there any way to set this up so I can both read and send input, but still have it running in the background?

I'd also like to be able to send input to the deamon from different processes as well (a shell script that could send a "Stop\n" command, for instance)

share|improve this question
add comment

1 Answer

up vote 8 down vote accepted

Read from a pipe, write to a file

If you want the daemon to read input produced by some arbitrary process, you need to connect that process to a pipe. Here the arbitrary process is you echoing commands, and it's going to run in a different context. So create a named pipe (often called a fifo in unix contexts).

mkfifo /var/run/daemon.fifo
</var/run/daemon.fifo /path/to/daemond --option >daemon.log

And just write commands to the pipe:

echo 'FORWARD 10' >/var/run/daemon.fifo
echo 'LEFT 72' >/var/run/daemon.fifo

This is unlikely to work as is however: there's a good chance that the daemon will exit when it sees an end of file on its standard input, which happens as soon as the first process that writes to the pipe terminates. You can use tail -f to avoid that problem.

</var/run/daemon.fifo tail -c +1 -f | {
  echo $$ >/var/run/daemon.pid
  exec /path/to/daemond --option >daemon.log
}

With some tail implementations, you may get bitten by buffering: the tail process will wait until it has amassed enough bytes to emit some output. I don't think this is solvable in the POSIX toolbox; if that's a problem, use a trivial C or Perl or Python program. As far as I can tell the tail from GNU coreutils (as found on Linux and elsewhere) is safe on this respect.

When you stop the daemon, echo >/var/run/daemon.fifo will kill the tail process.


Starting the program inside screen

Instead of invoking the daemon directly from your service manager (are you really using just SysV init, or something additional like wrapper scripts or Upstart?), invoke

screen -c daemon.screenrc -L -d -m -S daemon_name /path/to/daemond --option

Since the daemon won't be a child process of the service manager, you need to make sure to send a signal to the right process. How to do that depends on exactly how the daemon is started and by what.

It's technically possible to attach a running process to a terminal, but there's a risk you'll crash the program, so this is definitely out for a production system.

The -L option makes screen write everything that appears in its window to a file. The file name is given in daemon.screenrc with the logfile directive.

share|improve this answer
    
Actually, I'd really like to be able to send messages to it's stdin from a script--maybe that's the question I should have asked. Currently I'm just running the server from a script and am able to type to it in a terminal, but it just seems like it should be running as a service... –  Bill K Dec 22 '10 at 22:46
    
@Bill: Ok, I see. Then the first thing that comes to my mind is a named pipe. –  Gilles Dec 22 '10 at 23:43
    
I think this is exactly what I want @Gilles! I need to understand it better though. I'll spend some time sorting through man pages to figure it out--I honestly get very little of that (I get most of what you are doing and almost none of how you did it--and I thought I kind of had a clue with this stuff.) My theory wasn't to connect directly to the process but to create yet another script that joined it's i/o to the deamons o/i to make it seem like the original console is running, but with the ability to do the echo 'FORWARD 10' from another script at the same time. –  Bill K Dec 23 '10 at 0:06
    
I think I get much of it. If I break it down I now understand "mkfifo pipe" and "tail -f pipe | command > output", tested those and they work. I think most of the other stuff you had was tricks to get it to run on one line--am I missing anything critical? –  Bill K Dec 23 '10 at 0:23
    
@Bill: You could write to the terminal inside screen from the outside (using screen's stuff command). But you don't need the overhead (processing, but most importantly cognitive) of a terminal here, a pipe is almost enough (it's enough with a little end-of-file-ignoring relay process). You may want to experiment a little with <fifo cat or <fifo tail -f | cat in one terminal and echo >fifo; echo >fifo in another terminal; I think you'll be fine. –  Gilles Dec 23 '10 at 0:43
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.