Skip to content

Commit 00de16f

Browse files
committed
Do not capture output for run_cmd!() and spawn!()
Or output from long running process would be blocked Fixed #30
1 parent 0b6e05b commit 00de16f

File tree

5 files changed

+45
-16
lines changed

5 files changed

+45
-16
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ println!("get result: {}", run_fun!(my_cmd)?);
230230
`spawn!()` macro executes the whole command as a child process, returning a handle to it. By
231231
default, stdin, stdout and stderr are inherited from the parent.
232232

233-
To get result, you can call `wait_cmd_result()` or `wait_fun_result()` to get CmdResult/FunResult.
233+
With `spawn_with_output!()` you can get output result by calling `wait_fun_result()`.
234234

235235
```rust
236236
spawn!(ping -c 10 192.168.0.1)?.wait_cmd_result()?;
237-
let output = spawn!(/bin/cat file.txt | sed s/a/b/)?.wait_fun_result()?;
237+
let output = spawn_with_output!(/bin/cat file.txt | sed s/a/b/)?.wait_fun_result()?;
238238
```
239239

240240

examples/rust_cookbook.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn main() -> CmdResult {
2727
run_cmd!(rm -f out.txt)?;
2828

2929
// Continuously process child process' outputs
30-
spawn!(journalctl)?.wait_with_pipe(&mut |pipe| {
30+
spawn_with_output!(journalctl)?.wait_with_pipe(&mut |pipe| {
3131
BufReader::new(pipe)
3232
.lines()
3333
.filter_map(|line| line.ok())

macros/src/lib.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,36 @@ pub fn spawn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
185185
let cmds = lexer::Lexer::new(input.into()).scan().parse(true);
186186
quote! ({
187187
use ::cmd_lib::AsOsStr;
188-
#cmds.spawn()
188+
#cmds.spawn(false)
189+
})
190+
.into()
191+
}
192+
193+
/// Run commands with/without pipes as a child process, returning a handle to capture the
194+
/// final output
195+
/// ```no_run
196+
/// # use cmd_lib::*;
197+
/// // from examples/dd_test.rs:
198+
/// let mut procs = vec![];
199+
/// for _ in 0..4 {
200+
/// let proc = spawn_with_output!(
201+
/// sudo bash -c "dd if=$file of=/dev/null bs=$block_size skip=$off count=$cnt 2>&1"
202+
/// )?;
203+
/// }
204+
///
205+
/// for (i, mut proc) in procs.into_iter().enumerate() {
206+
/// let output = proc.wait_fun_result()?;
207+
/// run_cmd!(info "thread $i bandwidth: $bandwidth MB/s")?;
208+
/// }
209+
/// # Ok::<(), std::io::Error>(())
210+
/// ```
211+
#[proc_macro]
212+
#[proc_macro_error]
213+
pub fn spawn_with_output(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
214+
let cmds = lexer::Lexer::new(input.into()).scan().parse(true);
215+
quote! ({
216+
use ::cmd_lib::AsOsStr;
217+
#cmds.spawn(true)
189218
})
190219
.into()
191220
}

src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,12 @@
255255
//! `spawn!()` macro executes the whole command as a child process, returning a handle to it. By
256256
//! default, stdin, stdout and stderr are inherited from the parent.
257257
//!
258-
//! To get result, you can call `wait_cmd_result()` or `wait_fun_result()` to get CmdResult/FunResult.
258+
//! With `spawn_with_output!()` you can get output result by calling `wait_fun_result()`.
259259
//!
260260
//! ```no_run
261-
//! # use cmd_lib::spawn;
261+
//! # use cmd_lib::*;
262262
//! spawn!(ping -c 10 192.168.0.1)?.wait_cmd_result()?;
263-
//! let output = spawn!(/bin/cat file.txt | sed s/a/b/)?.wait_fun_result()?;
263+
//! let output = spawn_with_output!(/bin/cat file.txt | sed s/a/b/)?.wait_fun_result()?;
264264
//! # Ok::<(), std::io::Error>(())
265265
//! ```
266266
//!
@@ -322,7 +322,7 @@
322322
323323
pub use cmd_lib_macros::{
324324
cmd_debug, cmd_die, cmd_echo, cmd_error, cmd_info, cmd_trace, cmd_warn, export_cmd, run_cmd,
325-
run_fun, spawn, use_builtin_cmd, use_custom_cmd,
325+
run_fun, spawn, spawn_with_output, use_builtin_cmd, use_custom_cmd,
326326
};
327327
/// Return type for run_fun!() macro
328328
pub type FunResult = std::io::Result<String>;

src/process.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,10 @@ impl GroupCmds {
138138
}
139139
}
140140

141-
pub fn spawn(mut self) -> Result<CmdChildren> {
141+
pub fn spawn(mut self, with_output: bool) -> Result<CmdChildren> {
142142
assert_eq!(self.group_cmds.len(), 1);
143143
let mut cmds = self.group_cmds.pop().unwrap().0;
144-
let ret = cmds.spawn(&mut self.current_dir);
144+
let ret = cmds.spawn(&mut self.current_dir, with_output);
145145
if let Err(ref err) = ret {
146146
error!("Spawning {} failed, Error: {}", cmds.get_full_cmds(), err);
147147
}
@@ -170,7 +170,7 @@ impl Cmds {
170170
&self.full_cmds
171171
}
172172

173-
fn spawn(&mut self, current_dir: &mut PathBuf) -> Result<CmdChildren> {
173+
fn spawn(&mut self, current_dir: &mut PathBuf, with_output: bool) -> Result<CmdChildren> {
174174
if std::env::var("CMD_LIB_DEBUG") == Ok("1".into()) {
175175
debug!("Running {} ...", self.get_full_cmds());
176176
}
@@ -189,19 +189,19 @@ impl Cmds {
189189
} else {
190190
cmd.setup_redirects(&mut last_pipe_in, None)?;
191191
}
192-
let child = cmd.spawn(current_dir)?;
192+
let child = cmd.spawn(current_dir, with_output)?;
193193
children.push(child);
194194
}
195195

196196
Ok(CmdChildren::from(children))
197197
}
198198

199199
fn run_cmd(&mut self, current_dir: &mut PathBuf) -> CmdResult {
200-
self.spawn(current_dir)?.wait_cmd_result_nolog()
200+
self.spawn(current_dir, false)?.wait_cmd_result_nolog()
201201
}
202202

203203
fn run_fun(&mut self, current_dir: &mut PathBuf) -> FunResult {
204-
self.spawn(current_dir)?.wait_fun_result_nolog()
204+
self.spawn(current_dir, true)?.wait_fun_result_nolog()
205205
}
206206
}
207207

@@ -337,7 +337,7 @@ impl Cmd {
337337
self
338338
}
339339

340-
fn spawn(mut self, current_dir: &mut PathBuf) -> Result<CmdChild> {
340+
fn spawn(mut self, current_dir: &mut PathBuf, with_output: bool) -> Result<CmdChild> {
341341
let arg0 = self.arg0();
342342
let full_cmd = self.debug_str();
343343
if arg0 == "cd" {
@@ -411,7 +411,7 @@ impl Cmd {
411411
// update stdout
412412
if let Some(redirect_out) = self.stdout_redirect.take() {
413413
cmd.stdout(redirect_out);
414-
} else {
414+
} else if with_output {
415415
cmd.stdout(Stdio::piped());
416416
}
417417

0 commit comments

Comments
 (0)