CLI app with a running process in the background

I'm creating a little CLI application, mostly in study cases.

The application listens to messages from the live chat through WebSockets and parses them to save in storage if a message contains some user-defined pattern.

I want to use something like a similar approach used for Docker containers (at least, as I see it) because I find this more suitable. For example, to start to listen to a chat, a user types chatspy start --chat <chat-name> --pattern <pattern-name>, this starts a process of listening logic in the background. If a user wants to add a new chat to listen, he types chatspy add chat <chat-name>. Then the user types something like chatspy stop --all or chatspy stop --chat <chat-name> to stop the application/listening of the exact chat.

The most challenging part is that I don't properly understand how to create and control this process in the background. As I see, I need to create a new daemon from the Rust CLI handler code when a user starts the application. But then I don't understand how do I suppose to communicate with this daemon, because creating particularly the same interface for the daemon doesn't look nice to me.

How would you implement this? Will be happy to receive any feedback or links.

If you need more specific information, I can provide it.

You could spin up a little raw TCP server and read commands line-by-line or something like that.

Docker uses an HTTP listener socket to communicate with the background daemon.

1 Like

When working on Unix/Linux/BSD, you could also use a UnixListener that works through a socket on the file system instead of a TCP port using the loopback interface.

A more modern way to control processes would be through D-Bus. See the zbus crate maybe.

1 Like

So these solutions mean that I need to create some kind of client-server approach, where the "server" would be the running daemon and the "client" is a CLI application?

Yes. The overall term is called inter-process communication.

1 Like

Great thanks for the tip.

Does exist a way where I can unite them together? Or it's completely okay to have a client-server in my case?

The only other option that comes to my mind is shared memory, semaphores, etc. for example. But also this is a form of inter-process communication (IPC).

I think it's not just "okay" but idiomatic. So I would see the background process as server that can be controlled by a client CLI program.

I believe it's the same what Firefox or Chrome do when they are running and someone, for example, invokes firefox https://somewebsite.example/. The CLI command will invoke D-Bus to talk to the running instance of the program and tell it to open a new window with the given URL. (Not sure, though, if it's D-Bus or another form of IPC being used.)

When using X11 firefox creates a hidden window on which it can receive events from another firefox process, thus allowing a remote firefox invocation to open a page on your local running firefox when using ssh with X forwarding. It also supports dbus for Wayland compatibility.

nsXRemoteServer.cpp - mozsearch for X11
nsDBusRemoteServer.cpp - mozsearch for DBus.

1 Like

If a project becomes big enough to serve a wide range of users from technical to casual then it'll often end up with multiple interfaces (CLI, TUI, GUI, scripting, remote APIs).

On the other hand if you're lazy and only doing this for personal use you can avoid the work of adding a remote interface by using things like screen or docker attach to reconnect to the TTY that the CLI is running on and then just have a simple interactive console to issue some commands.

Another mechanism that gets occasionally used is to have control/config files and listen to filesystem notifications to pick up changes.

1 Like

I will mark this post as a solution because this is the exact information I needed.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.