First of all I am new to Linux and Rust.
What I am trying to achieve is to print the timestamp to the terminal whenever a user execute a command in the terminal.
I have written a Rust program which will print the current timestamp on the right extreme of the terminal. I was planning to execute this program as systemd
service in the background using a bash script. What this bash script does is inside an infinite loop, check the key press and if it is Enter, then execute the rust program. Before I execute the real Rust program, I just tried to echo
a string. When I was running the service, I noticed that when I press Enter, echo
runs many times before it stops. I also tried to execute the Rust program instead of the echo
, but it didn't work the way I imagined. So my solution is wrong smewhere.
My question is, is my approach for this correct? I don't know whether running a background process with an infinite loop is good. This idea I took from the below video.
Creating systemd Service Files
This project is for educational purpose. I was inspired by the Powerline project and wanted to understand how it works and do something similar in small scale using Rust.
Could you guys let me know whether this approach is correct or point me to the right direction. Thanks
main.rs
extern crate termion;
extern crate chrono;
use std::time::SystemTime;
use std::io::stdout;
use chrono::{DateTime, Utc};
use termion::{color, terminal_size, cursor, raw::IntoRawMode, cursor::DetectCursorPos};
fn main() {
let mut stdout = stdout().into_raw_mode().unwrap();
let cursor_pos = stdout.cursor_pos().expect("Could not get the cursor position");
let time_now = SystemTime::now();
let datetime = DateTime::<Utc>::from(time_now);
let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S").to_string();
let size = terminal_size().expect("Could not get the terminal size");
let x = size.0 - (timestamp_str.len() - 1) as u16;
let y = cursor_pos.1;
print!("{}{red}{}{reset}",
cursor::Goto(x, y),
timestamp_str,
red = color::Fg(color::Red),
reset = color::Fg(color::Reset));
}
bash script
#!/bin/bash
IFS=
while true
do
read -n 1 key
if [ "$key" = "" ]; then
echo "This was really Enter, not space, tab or something else"
fi
done
logs from the service
Apr 04 20:49:42 archlinux systemd[1]: Started cmd-timestamp.service.
Apr 04 20:49:42 archlinux cmd-timestamp.sh[410670]: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code:>
Apr 04 20:49:42 archlinux cmd-timestamp.sh[410670]: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Apr 04 20:49:42 archlinux systemd[1]: cmd-timestamp.service: Main process exited, code=exited, status=101/n/a
Apr 04 20:49:42 archlinux systemd[1]: cmd-timestamp.service: Failed with result 'exit-code'.
Taking the comment to the answer section:
The easiest way to accomplish what I think you want is to hook your program into bash via the PROMPT_COMMAND
.
In your ~/.bashrc
(or ~/.bash_login
) set:
export PROMPT_COMMAND=/path/to/rust/executable