Whats is the standard way apps which run on the command line communicate to its daemon process?
There are a number of ways to do this:
Dropboxes and Signals
A variety of locations are being used to store "pid files" containing a daemon's process ID number: /var/run/<app>/<app>.pid
, /var/run/<app>.pid
(thanks @Adam Katz for edit), /run/<app>/<app>.pid
, /run/<app>.pid
, (see Askubuntu: Why has /var/run been migrated to /run?).
When the pid
of the daemon process is known, a command line program (which is running as a separate process) could communicate with the daemon in these ways:
- Writing something into a prearranged place. This could be an ordinary file, a database table, or any convenient spot readable by the server.
- Sending a signal to the daemon. The common way to do this locally is with the kill system call,
int kill(pid_t pid, int sig);
.
Old School Example: The server multiplexing daemon xinetd would reread its configuration file after receiving SIGHUP.
The send-a-signal methodology has been made redundant by the inotify
API whereby a process can subscribe to file system events. Using signals is useful when you don't want the daemon to act on every file change, since not every change may leave the file in a valid state, as when modifying a system config file.
FIFO or Pipe
A fifo or pipe is simply a special file that blocks processes reading it until some other process has written to it. You can make a named pipe/fifo in the file system with mkfifo
. The only tricky thing about this is that pipes should generally be opened unbuffered, e.g. with open()
as opposed to fopen()
. Scripting languages sometimes make a facility for pipe-friendly reading/writing: Perl
had a line-buffered
mode set with $|=1
that was useful for pipes.
More commonly, you see anonymous pipes all the time on the command line with the |
symbol separating commands which are executed as separate processes.
Sockets
What about something newer, like mySQL? The mysql
database system consists of a command line client mysql
and a server mysqld
and may also serve other clients either on the local machine or over the internet.
mySQL communicates using a socket
. The server listens to a socket for connections, and forks new processes giving a socket descriptor to the child for processing. When the child is done processing, it can exit.
There are UNIX sockets and Internet sockets, with different namespaces. One guide to programming sockets in C on Linux would be the sockets chapter of the The GNU C Library manual.
No-wait I/O is an alternative to forking off processes. This is done in C with the select()
system call, which allows having a process wait for an event on one or more files, including sockets, or a timeout. The GNU C Library docs includes a no-wait I/O socket server example
NodeJS is a server for the Javascript language, written as a single-threaded server using no-wait I/O, and shows that these techniques are still relevant in modern systems.
"Callbacks"
I'm assuming its impossible to ask linux to call a callback when I type in myapp foo bar?
Maybe. But it might be too much work to be worth the trouble.
When you type myapp foo bar
into "Linux", that's not Linux, you are typing that into your command shell, which is a program running in its own process separate from everything else.
So, unless the functionality you want is built into the command shell, there is normally no way for that command shell to send messages to your other program without starting a new process.
The default command shell for many (but not all) Linux systems is /bin/bash
. To communicate with a daemon that listens to sockets from bash
we would need a socket opening procedure in bash
. And, sure enough, it exists!
One can listen to a socket in bash
. This is the basis for a daemon:
From: Simple Socket Server in Bash? answer by dtmilano:
Q: I have a simple debugging solution which writes things to 127.0.0.1:4444 and I'd like to be able to simply bind up a port from bash and print everything that comes across. Is there an easy way to do this?
A:
$ exec 3<>/dev/tcp/127.0.0.1/4444
$ cat <&3
One can also open a socket from bash to a remote process, i.e. communicate with a a daemon:
From: TCP connection, bash only
we learn exec 5<>"/dev/tcp/${SERVER}/${PORT}"
redirects a TCP link to file descriptor 5 for both input and output.
Not all bash
programs are compiled with TCP support. It is apparently Linux-distribution dependent. At least according to a comment on this answer by William Pursell
There are other shells besides bash
. Many shells were developed back in the *nix days. ksh
Korn shell. csh
C-shell. Bourne shell sh
. Ash shell. Wikipedia keeps a list of shells. And these shells each have their own advantages and disadvantages and are not entirely compatible with each other's formatting!
Fast forward about 30 years, and there aren't so many in common use now.
But an important feature exists here: each user can choose his own login shell. See the chsh
command.
So where I am going here is that if bash
doesn't support the communications you need to do, you could set up a command shell where special messages can be sent without opening a new process. This might save you a few milliseconds, and usually isn't worth it. But nothing is stopping you. You might even set up an ipython command shell, as suggested in https://stackoverflow.com/a/209670/103081, and python can import most anything you need to do socket communications with your specialized daemon.