Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Show logs after `rad node start`
Alexis Sellier committed 2 years ago
commit 613e3e526937188a7323354b145b602693073339
parent 2e6c9827a91066b410a9404aa1c7f1ea7db798ab
2 files changed +30 -21
modified radicle-cli/src/commands/node.rs
@@ -1,4 +1,5 @@
use std::ffi::OsString;
+
use std::time;

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))?;
            routing::run(&store, rid, nid, json)?;
        }
-
        Operation::Logs { lines } => control::logs(lines, true)?,
-
        Operation::Start { daemon, options } => control::start(daemon, options)?,
+
        Operation::Logs { lines } => control::logs(lines, Some(time::Duration::MAX), &profile)?,
+
        Operation::Start { daemon, options } => control::start(daemon, options, &profile)?,
        Operation::Status => {
            let node = Node::new(profile.socket());
-
            control::status(&node)?;
+
            control::status(&node, &profile)?;
        }
        Operation::Stop => {
            let node = Node::new(profile.socket());
modified radicle-cli/src/commands/node/control.rs
@@ -1,29 +1,28 @@
use std::ffi::OsString;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
-
use std::time::Duration;
-
use std::{process, thread};
+
use std::{process, thread, time};

use anyhow::Context as _;

use radicle::node::{Address, Handle as _, NodeId};
-
use radicle::profile;
use radicle::Node;
+
use radicle::{profile, Profile};

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
    // without `RAD_PASSPHRASE`. To keep things consistent, we also use this in foreground mode.
    let passphrase = term::io::passphrase(profile::env::RAD_PASSPHRASE)
        .context(format!("`{}` must be set", profile::env::RAD_PASSPHRASE))?;

    if daemon {
-
        let home = radicle::profile::home()?;
        let log = OpenOptions::new()
            .append(true)
            .create(true)
-
            .open(home.node().join("node.log"))?;
+
            .open(profile.home.node().join("node.log"))?;
+

        process::Command::new("radicle-node")
            .args(options)
            .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))
            .stderr(process::Stdio::null())
            .spawn()?;
+

+
        logs(0, Some(time::Duration::from_secs(1)), profile)?;
    } else {
        let mut child = process::Command::new("radicle-node")
            .args(options)
@@ -53,9 +54,8 @@ pub fn stop(node: Node) -> anyhow::Result<()> {
    Ok(())
}

-
pub fn logs(lines: usize, follow: bool) -> anyhow::Result<()> {
-
    let home = radicle::profile::home()?;
-
    let logs = home.node().join("node.log");
+
pub fn logs(lines: usize, follow: Option<time::Duration>, profile: &Profile) -> anyhow::Result<()> {
+
    let logs = profile.home.node().join("node.log");

    let mut file = BufReader::new(File::open(logs)?);
    file.seek(SeekFrom::End(-1))?;
@@ -78,17 +78,21 @@ pub fn logs(lines: usize, follow: bool) -> anyhow::Result<()> {
    }
    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))?;
-
        loop {
+

+
        let start = time::Instant::now();
+

+
        while start.elapsed() < timeout {
            let mut line = String::new();
            let len = file.read_line(&mut line)?;
+

            if len == 0 {
-
                thread::sleep(Duration::from_millis(250));
+
                thread::sleep(time::Duration::from_millis(250));
            } 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(())
}

-
pub fn status(node: &Node) -> anyhow::Result<()> {
+
pub fn status(node: &Node, profile: &Profile) -> anyhow::Result<()> {
    if node.is_running() {
        term::success!("The node is {}", term::format::positive("running"));
    } else {
        term::info!("The node is {}", term::format::negative("stopped"));
    }
-
    term::blank();
-

-
    logs(10, false)
+
    if profile.home.node().join("node.log").exists() {
+
        term::blank();
+
        // If we're running the node via `systemd` for example, there won't be a log file
+
        // and this will fail.
+
        logs(10, None, profile)?;
+
    }
+
    Ok(())
}