Whats the easiest way to send messages to my linux daemon app?
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.
Is it possible to pass input to a running service or daemon?
On Linux, all running processes have a special directory under /proc
containing information and hooks into the process. Each subdirectory of /proc
is the PID of a running process. So if you know the PID of a particular process you can get information about it. E.g.:
$ sleep 100 & ls /proc/$!
...
cmdline
...
cwd
environ
exe
fd
fdinfo
...
status
...
Of note is the fd
directory, which contains all the file descriptors associated with the process. 0
, 1
, and 2
exist for (almost?) all processes, and 0
is the default stdin. So writing to /proc/$PID/fd/0
will write to that process' stdin.
A more robust alternative is to set up a named pipe connected to your process' stdin; then you can write to that pipe and the process will read it without needing to rely on the /proc
file system.
See also Writing to stdin of background process on ServerFault.
Send message to a Python daemon script from another init script without using IPC
You can use named pipe. First you instantiate named pipe using mkfifo
, which creates file representing the pipe. Then you open this file in both scripts - in one for writing and in another one for reading. After that you can just write some data to the opened file in one script and read it back in another.
Note that pipes are unidirectional, which means that if you need to communicate in both directions, then you need to create two pipes.
A simple way to send mails from a C application on Unix
Here's a nice SMTP library, libESMTP
Custom Linux service status message using Java Service Wrapper
I got a half-solution. Inspecting the wrapper script code, as suggested by @Naytzyrhc, I found that the wrapper lib reads 3 files to create the status message:
bin/my-app.pid
to print the PID of the running process;bin/my-app.status
to print the status of the wrapper itself;bin/my-app.java.status
to print the status of the wrapped application.
So, in the application code, to override the status message, just write the message in the my-app.java.status
file.
There's only one gotcha: if the status message contains line breaks, the service my-app status
doesn't print them, because it uses the echo
command (as stated in this question Capturing multiple line output into a Bash variable). To solve this problem, just change the line from:
eval echo `gettext '$APP_LONG_NAME is running: PID:$pid, Wrapper:$STATUS, Java:$JAVASTATUS'`
to:
eval echo `gettext '$APP_LONG_NAME is running: PID:$pid, Wrapper:$STATUS, Java:"$JAVASTATUS"'`
(Using double quotes on $JAVASTATUS
).
This is a half-solution because it doesn't fire an event to the running application, as I wanted. But it works for customizing the status message: it depends on the application how often the message is updated.
Related Topics
Producer Consumer Implementation in a Block Device Driver
How to Disable Floating Point Unit (Fpu)
Why Do Es and Ds Zero Out Eventually on 64 Bit Kernel When Set to Tls Selectors
How Convert Address in Elf to Physical Address
How Does Sort Work Out How Much Ram There Is
How to Make Library Installed from Opam Available to Ocaml
Slurm: After Allocating All Gpus No More CPU Job Can Be Submitted
How to Introspect Normal World from Secure World Using Trustzone
Mount -T Cifs Works on One Version of Linux But Not Another
Find Ip Address of My System for a Particular Interface with Shell Script (Bash)
How to Do "For Each" on Output from Find
In Linux, Do There Exist Functions Similar to _Clearfp() and _Statusfp()
Difference Between "Cpu/Mem-Loads/Pp" and "Cpu/Mem-Loads/"
Linux Nasm Move a Value in Al Up to Ax
Question About Epoll and Splice
Capturing User-Space Assembly with Ftrace and Kprobes (By Using Virtual Address Translation)