refactor
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
use std::process::Stdio;
|
||||
|
||||
use tokio::{
|
||||
io::{AsyncRead, AsyncReadExt},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
pub async fn execute(command: &str, max_output_bytes: u64) -> (i32, String, String) {
|
||||
let mut child = match Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(command)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(child) => child,
|
||||
Err(error) => return (-1, String::new(), error.to_string()),
|
||||
};
|
||||
|
||||
let Some(stdout) = child.stdout.take() else {
|
||||
return (-1, String::new(), "stdout pipe unavailable".to_string());
|
||||
};
|
||||
let Some(stderr) = child.stderr.take() else {
|
||||
return (-1, String::new(), "stderr pipe unavailable".to_string());
|
||||
};
|
||||
|
||||
let (stdout_data, stderr_data) = tokio::join!(
|
||||
read_limited_output(stdout, max_output_bytes),
|
||||
read_limited_output(stderr, max_output_bytes),
|
||||
);
|
||||
|
||||
child.kill().await.ok();
|
||||
let exit_code = child
|
||||
.wait()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|status| status.code())
|
||||
.unwrap_or(-1);
|
||||
|
||||
(
|
||||
exit_code,
|
||||
String::from_utf8_lossy(&stdout_data).into_owned(),
|
||||
String::from_utf8_lossy(&stderr_data).into_owned(),
|
||||
)
|
||||
}
|
||||
|
||||
async fn read_limited_output<R>(reader: R, max_output_bytes: u64) -> Vec<u8>
|
||||
where
|
||||
R: AsyncRead + Unpin,
|
||||
{
|
||||
let mut buffer = Vec::new();
|
||||
let _ = reader.take(max_output_bytes).read_to_end(&mut buffer).await;
|
||||
buffer
|
||||
}
|
||||
Reference in New Issue
Block a user