diff --git a/Cargo.lock b/Cargo.lock index ab3cd23d..1e5b6efb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -773,7 +773,7 @@ dependencies = [ [[package]] name = "pueue" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index dd3ed0ee..528a7f26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pueue" description = "A cli tool for managing long running shell commands." -version = "0.1.0" +version = "0.1.1" authors = ["Arne Beer "] homepage = "https://github.com/nukesor/pueue" repository = "https://github.com/nukesor/pueue" diff --git a/README.md b/README.md index e0d38ec3..dc869327 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,13 @@ This would help me a lot! ## Starting the Daemon +### Local +Just run `pueued` anywhere on your commandline. It'll exit if you close the terminal, though. + +### Background +To fork `pueued` into the background, add the `-d` or `--daemonize` flag. E.g. `pueued -d`. \ +The daemon can be then shut down using the client: `pueue shutdown` + ### Systemd If you use Systemd and don't install Pueue with a package manager, place `pueued.service` in `/etc/systemd/user/`. Afterward, every user can start/enable their own session with: @@ -170,10 +177,6 @@ Afterward, every user can start/enable their own session with: systemctl --user start pueued.service systemctl --user enable pueued.service -### Local -Just run `pueued` anywhere on your commandline. It'll exit if you close the terminal, though. - - ## Utilities ### JSON Support diff --git a/daemon/cli.rs b/daemon/cli.rs index d4dff562..c197c1fd 100644 --- a/daemon/cli.rs +++ b/daemon/cli.rs @@ -15,7 +15,7 @@ pub struct Opt { /// Closing the terminal won't kill the daemon any longer. /// This should be avoided and rather be properly done using a service manager. #[structopt(short, long)] - daemonize: bool, + pub daemonize: bool, // /// The ip the daemon listens on. Overwrites the address in the config file // #[structopt(short, long)] diff --git a/daemon/main.rs b/daemon/main.rs index 2d82c416..e34060f5 100644 --- a/daemon/main.rs +++ b/daemon/main.rs @@ -1,5 +1,6 @@ use ::anyhow::{bail, Error, Result}; use ::simplelog::{Config, LevelFilter, SimpleLogger}; +use ::std::process::Command; use ::std::fs::create_dir_all; use ::std::path::Path; use ::std::sync::mpsc::channel; @@ -34,6 +35,10 @@ async fn main() -> Result<()> { // Parse commandline options let opt = Opt::from_args(); + if opt.daemonize { + fork_daemon(&opt)?; + } + // Set the verbosity level for the client app if opt.verbose >= 3 { SimpleLogger::init(LevelFilter::Debug, Config::default())?; @@ -63,7 +68,7 @@ async fn main() -> Result<()> { } /// Initialize all directories needed for normal operation -pub fn init_directories(path: &String) { +fn init_directories(path: &String) { let pueue_dir = Path::new(path); if !pueue_dir.exists() { if let Err(error) = create_dir_all(&pueue_dir) { @@ -93,3 +98,25 @@ pub fn init_directories(path: &String) { } } } + +/// This is a simple and cheap custom fork method +/// Simply spawn a new child with identical arguments and exit right away +fn fork_daemon(opt: &Opt) -> Result<()> { + let mut arguments = Vec::::new(); + + if let Some(port) = &opt.port { + arguments.push("--port".to_string()); + arguments.push(port.clone()); + } + + if opt.verbose > 0 { + arguments.push("-".to_string() + &" ".repeat(opt.verbose as usize)); + } + + Command::new("pueued") + .args(&arguments) + .spawn()?; + + println!("Pueued is now running in the background"); + std::process::exit(0); +} diff --git a/shared/protocol.rs b/shared/protocol.rs index 7a0924b4..54c83166 100644 --- a/shared/protocol.rs +++ b/shared/protocol.rs @@ -1,6 +1,7 @@ use ::anyhow::Result; use ::async_std::net::TcpStream; use ::async_std::prelude::*; +use ::log::debug; use ::byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use ::std::io::Cursor; @@ -9,6 +10,7 @@ use crate::message::*; /// Convenience wrapper around send_bytes /// Deserialize a message and feed the bytes into send_bytes pub async fn send_message(message: &Message, socket: &mut TcpStream) -> Result<()> { + debug!("Sending message: {:?}", message); // Prepare command for transfer and determine message byte size let payload = serde_json::to_string(message) .expect("Failed to serialize message.") @@ -70,6 +72,7 @@ pub async fn receive_message(socket: &mut TcpStream) -> Result { // Deserialize the message let message = String::from_utf8(payload_bytes)?; + debug!("Received message: {:?}", message); let message: Message = serde_json::from_str(&message)?; Ok(message)