Issue
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:
class="lang-rust prettyprint-override">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"
Answered By - Diego Torres Milano Answer Checked By - Terry (WPSolving Volunteer)