123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- use std::io;
- use std::process::{ExitStatus, Stdio};
- use tokio::io::{AsyncBufReadExt, BufReader};
- use tokio::process::{Command};
- use crate::logger::{LogWriter};
- use crate::syscall::error::ExecError;
- fn _exitstatus_convert(res: io::Result<ExitStatus>) -> Result<Option<i32>, ExecError> {
- match res {
- Ok(es) => {
- match es.code() {
- None => {
- Ok(None)
- }
- Some(code) => {
- Ok(Some(code))
- }
- }
- }
- Err(e) => {Err(ExecError::from(e))}
- }
- }
- pub fn shell_exec_cmd(program: String) {
- let r = exec_blocking(program);
- match r {
- Ok(ec) => {
- match ec {
- None => {
- println!("exit with no code.")
- }
- Some(c) => {
- println!("exit with code {}.", c)
- }
- }
- }
- Err(err) => {
- println!("failed run command: {:?}.", err)
- }
- }
- }
- pub fn exec_blocking(program: String) -> Result<Option<i32>, ExecError> {
- let p = std::process::Command::new(program.clone()).spawn();
- match p {
- Ok(mut ch) => {
- let res = ch.wait();
- _exitstatus_convert(res)
- }
- Err(err) => {
- Err(ExecError::from(err))
- }
- }
- }
- pub async fn exec_async(program: String) -> Result<Option<i32>, ExecError> {
- let p = tokio::process::Command::new(program.clone()).spawn();
- match p {
- Ok(mut ch) => {
- let res = ch.wait().await;
- _exitstatus_convert(res)
- }
- Err(err) => {
- Err(ExecError::from(err))
- }
- }
- }
- pub async fn exec_async_with_logger(bin: String, stdout_logger: LogWriter, stderr_logger: LogWriter) -> Result<Option<i32>, ExecError> {
- let mut cmd_run = Command::new(&bin)
- .stdin(Stdio::null())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn()?;
- let cmd_stdout = match cmd_run.stdout.take() {
- None => {
- return Err(ExecError::from_str("can not take stdout for child process"))
- }
- Some(v) => {v}
- };
- let cmd_stderr = match cmd_run.stderr.take(){
- None => {
- return Err(ExecError::from_str("can not take stderr for child process"))
- }
- Some(v) => {v}
- };
- let stdout_reader = BufReader::new(cmd_stdout);
- let stderr_reader = BufReader::new(cmd_stderr);
- let mut stdout_lines = stdout_reader.lines();
- let mut stderr_lines = stderr_reader.lines();
- let bin_name_for_stdout_error_msg = bin.clone();
- tokio::spawn(async move {
- while let Some(line) = stdout_lines.next_line().await.unwrap_or_else(|e| {
- eprintln!("error in reading stdout for '{}':{:?}", bin_name_for_stdout_error_msg, e);
- None
- }) {
- stdout_logger.info(line.as_str()).await;
- }
- });
- let bin_name_for_stderr_error_msg = bin.clone();
- tokio::spawn(async move {
- while let Some(line) = stderr_lines.next_line().await.unwrap_or_else(|e| {
- eprintln!("error in reading stderr for '{}':{:?}", bin_name_for_stderr_error_msg, e);
- None
- }) {
- stderr_logger.warn(line.as_str()).await;
- }
- });
- let run_result = cmd_run.wait().await;
- _exitstatus_convert(run_result)
- }
|