cli: Show logs after `rad node start`
When the node is started, we show the first few log lines.
This commit is contained in:
parent
2e6c9827a9
commit
613e3e5269
|
|
@ -1,4 +1,5 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
use std::time;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
|
@ -210,11 +211,11 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
|
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
|
||||||
routing::run(&store, rid, nid, json)?;
|
routing::run(&store, rid, nid, json)?;
|
||||||
}
|
}
|
||||||
Operation::Logs { lines } => control::logs(lines, true)?,
|
Operation::Logs { lines } => control::logs(lines, Some(time::Duration::MAX), &profile)?,
|
||||||
Operation::Start { daemon, options } => control::start(daemon, options)?,
|
Operation::Start { daemon, options } => control::start(daemon, options, &profile)?,
|
||||||
Operation::Status => {
|
Operation::Status => {
|
||||||
let node = Node::new(profile.socket());
|
let node = Node::new(profile.socket());
|
||||||
control::status(&node)?;
|
control::status(&node, &profile)?;
|
||||||
}
|
}
|
||||||
Operation::Stop => {
|
Operation::Stop => {
|
||||||
let node = Node::new(profile.socket());
|
let node = Node::new(profile.socket());
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,28 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
|
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
|
||||||
use std::time::Duration;
|
use std::{process, thread, time};
|
||||||
use std::{process, thread};
|
|
||||||
|
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
|
|
||||||
use radicle::node::{Address, Handle as _, NodeId};
|
use radicle::node::{Address, Handle as _, NodeId};
|
||||||
use radicle::profile;
|
|
||||||
use radicle::Node;
|
use radicle::Node;
|
||||||
|
use radicle::{profile, Profile};
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
|
|
||||||
pub fn start(daemon: bool, options: Vec<OsString>) -> anyhow::Result<()> {
|
pub fn start(daemon: bool, options: Vec<OsString>, profile: &Profile) -> anyhow::Result<()> {
|
||||||
// Ask passphrase here, otherwise it'll be a fatal error when running the daemon
|
// Ask passphrase here, otherwise it'll be a fatal error when running the daemon
|
||||||
// without `RAD_PASSPHRASE`. To keep things consistent, we also use this in foreground mode.
|
// without `RAD_PASSPHRASE`. To keep things consistent, we also use this in foreground mode.
|
||||||
let passphrase = term::io::passphrase(profile::env::RAD_PASSPHRASE)
|
let passphrase = term::io::passphrase(profile::env::RAD_PASSPHRASE)
|
||||||
.context(format!("`{}` must be set", profile::env::RAD_PASSPHRASE))?;
|
.context(format!("`{}` must be set", profile::env::RAD_PASSPHRASE))?;
|
||||||
|
|
||||||
if daemon {
|
if daemon {
|
||||||
let home = radicle::profile::home()?;
|
|
||||||
let log = OpenOptions::new()
|
let log = OpenOptions::new()
|
||||||
.append(true)
|
.append(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(home.node().join("node.log"))?;
|
.open(profile.home.node().join("node.log"))?;
|
||||||
|
|
||||||
process::Command::new("radicle-node")
|
process::Command::new("radicle-node")
|
||||||
.args(options)
|
.args(options)
|
||||||
.env(profile::env::RAD_PASSPHRASE, passphrase)
|
.env(profile::env::RAD_PASSPHRASE, passphrase)
|
||||||
|
|
@ -31,6 +30,8 @@ pub fn start(daemon: bool, options: Vec<OsString>) -> anyhow::Result<()> {
|
||||||
.stdout(process::Stdio::from(log))
|
.stdout(process::Stdio::from(log))
|
||||||
.stderr(process::Stdio::null())
|
.stderr(process::Stdio::null())
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
||||||
|
logs(0, Some(time::Duration::from_secs(1)), profile)?;
|
||||||
} else {
|
} else {
|
||||||
let mut child = process::Command::new("radicle-node")
|
let mut child = process::Command::new("radicle-node")
|
||||||
.args(options)
|
.args(options)
|
||||||
|
|
@ -53,9 +54,8 @@ pub fn stop(node: Node) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logs(lines: usize, follow: bool) -> anyhow::Result<()> {
|
pub fn logs(lines: usize, follow: Option<time::Duration>, profile: &Profile) -> anyhow::Result<()> {
|
||||||
let home = radicle::profile::home()?;
|
let logs = profile.home.node().join("node.log");
|
||||||
let logs = home.node().join("node.log");
|
|
||||||
|
|
||||||
let mut file = BufReader::new(File::open(logs)?);
|
let mut file = BufReader::new(File::open(logs)?);
|
||||||
file.seek(SeekFrom::End(-1))?;
|
file.seek(SeekFrom::End(-1))?;
|
||||||
|
|
@ -78,17 +78,21 @@ pub fn logs(lines: usize, follow: bool) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
tail.reverse();
|
tail.reverse();
|
||||||
|
|
||||||
print!("{}", String::from_utf8_lossy(&tail));
|
print!("{}", term::format::dim(String::from_utf8_lossy(&tail)));
|
||||||
|
|
||||||
if follow {
|
if let Some(timeout) = follow {
|
||||||
file.seek(SeekFrom::End(0))?;
|
file.seek(SeekFrom::End(0))?;
|
||||||
loop {
|
|
||||||
|
let start = time::Instant::now();
|
||||||
|
|
||||||
|
while start.elapsed() < timeout {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
let len = file.read_line(&mut line)?;
|
let len = file.read_line(&mut line)?;
|
||||||
|
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
thread::sleep(Duration::from_millis(250));
|
thread::sleep(time::Duration::from_millis(250));
|
||||||
} else {
|
} else {
|
||||||
print!("{line}");
|
print!("{}", term::format::dim(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,13 +117,17 @@ pub fn connect(node: &mut Node, nid: NodeId, addr: Address) -> anyhow::Result<()
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn status(node: &Node) -> anyhow::Result<()> {
|
pub fn status(node: &Node, profile: &Profile) -> anyhow::Result<()> {
|
||||||
if node.is_running() {
|
if node.is_running() {
|
||||||
term::success!("The node is {}", term::format::positive("running"));
|
term::success!("The node is {}", term::format::positive("running"));
|
||||||
} else {
|
} else {
|
||||||
term::info!("The node is {}", term::format::negative("stopped"));
|
term::info!("The node is {}", term::format::negative("stopped"));
|
||||||
}
|
}
|
||||||
|
if profile.home.node().join("node.log").exists() {
|
||||||
term::blank();
|
term::blank();
|
||||||
|
// If we're running the node via `systemd` for example, there won't be a log file
|
||||||
logs(10, false)
|
// and this will fail.
|
||||||
|
logs(10, None, profile)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue