linuxdaemonsystemd

Daemonize process in Linux bash


What is the most convenient way to interact with a rust library that needs to keep track of some internal state in the background.

For instance I have the following program:

use tokio::io::AsyncBufReadExt;

#[tokio::main]
async fn main() {
    let mut state = 0;

    let mut reader = tokio::io::BufReader::new(tokio::io::stdin());

    loop {
        let mut buffer = Vec::new();
        reader.read_until(b'\n', &mut buffer).await.unwrap();
        let cmd = std::str::from_utf8(&buffer).unwrap();

        match cmd {
            "get-count\n" => {
                println!("{}", state);
                state += 1;
            }
            _ => {

            }
        }
    }
}

which I can interact with in the following way using Linux bash:

cargo run
get-count
0
get-count
1
another-command
get-count
2

However, this creates a blocking process and I need to use inputs from other bash commands when interacting with the library.

My goal is to run this as a daemon process in such a way that I can interact with it in the following way using bash:

>> ./start-service
>> ./service-cli get-count
0
>>  ./service-cli get-count
1
>> COUNT=$(./service-cli get-count)
>> echo $COUNT
2

What is the best practice for this when using Linux? Are there any examples of how to do something like this using systemd?


Solution

  • You can use coproc to execute the desired command with the standard output and standard input of the command connected via a pipe file descriptor.

    coproc cargo run
    

    then

    echo get-count  >&"${COPROC[1]}"
    

    and

    read -u "${COPROC[0]}" count
    echo "$count"