67 lines
1.9 KiB
Rust
67 lines
1.9 KiB
Rust
//! Reads a unit journal, with optional live output through the world watcher.
|
|
use sausage_init::name;
|
|
use std::{
|
|
fs,
|
|
io::{self, Write},
|
|
};
|
|
fn run() -> io::Result<()> {
|
|
let mut args = std::env::args().skip(1);
|
|
let (mut unit, mut lines, mut follow) = (String::new(), 10usize, false);
|
|
while let Some(arg) = args.next() {
|
|
match arg.as_str() {
|
|
"-u" => {
|
|
unit = name(
|
|
&args
|
|
.next()
|
|
.ok_or_else(|| io::Error::other("missing unit"))?,
|
|
)
|
|
}
|
|
"-n" => {
|
|
lines = args
|
|
.next()
|
|
.and_then(|n| n.parse().ok())
|
|
.ok_or_else(|| io::Error::other("missing count"))?
|
|
}
|
|
"-f" => follow = true,
|
|
"--no-pager" => (),
|
|
_ => return Err(io::Error::other("unknown argument")),
|
|
}
|
|
}
|
|
let path = format!("/var/log/journal/{unit}.log");
|
|
let watcher = sausage_spawn::Watcher::new(&[path.clone()]);
|
|
let bytes = fs::read(&path).unwrap_or_default();
|
|
let mut starts = vec![0];
|
|
for (i, b) in bytes.iter().enumerate() {
|
|
if *b == b'\n' && i + 1 < bytes.len() {
|
|
starts.push(i + 1);
|
|
}
|
|
}
|
|
let start = if lines == 0 {
|
|
bytes.len()
|
|
} else {
|
|
starts[starts.len().saturating_sub(lines)]
|
|
};
|
|
io::stdout().write_all(&bytes[start..])?;
|
|
io::stdout().flush()?;
|
|
let mut offset = bytes.len();
|
|
while follow {
|
|
let pollable = watcher.subscribe();
|
|
pollable.block();
|
|
drop(pollable);
|
|
watcher.changes();
|
|
let bytes = fs::read(&path).unwrap_or_default();
|
|
if bytes.len() < offset {
|
|
offset = 0;
|
|
}
|
|
io::stdout().write_all(&bytes[offset..])?;
|
|
io::stdout().flush()?;
|
|
offset = bytes.len();
|
|
}
|
|
Ok(())
|
|
}
|
|
fn main() {
|
|
if run().is_err() {
|
|
std::process::exit(1);
|
|
}
|
|
}
|