< 返回版块

liberwang1013 发表于 2021-08-13 12:06

Tags:tokio,process

use axum::prelude::*;

use std::{net::SocketAddr, process::Stdio};
use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};

async fn run_process(cmd: &str) -> Result<String, Box<dyn std::error::Error>> {
    println!("cmd: {}", cmd);
    let mut command = tokio::process::Command::new("sh");
    command.arg("-c").arg(std::ffi::OsStr::new(cmd.clone()));
    //command.arg("-c").arg(std::ffi::OsString::from(cmd.clone()).as_os_str());
    //command.arg("-c").arg("sleep 60");
    command.stdout(Stdio::piped());

    let mut child = command.spawn()?;

    let stdout = child
        .stdout
        .take()
        .expect("child did not have a handle to stdout");

    let mut reader = BufReader::new(stdout).lines();
    tokio::spawn(async move {
        let status = child
            .wait()
            .await
            .expect("child process encountered an error");

        println!("child status was: {}", status);
    });

    let mut output: String = "".into();
    while let Some(line) = reader.next_line().await? {

        println!("Line: {}", line);
        output.push_str(&line);
    }

    println!("Hello, world!");
    Ok(output)
}

async fn run_tcp_server() -> Result<(), Box<dyn std::error::Error>> {
    let listener = tokio::net::TcpListener::bind("127.0.0.1:18080").await?;
    loop {
        let (mut socket, _) = listener.accept().await?;

        tokio::spawn(async move {
            let mut buf = vec![0u8; 128];
            while let Ok(n) = socket.read(&mut buf).await {

                let new_buf = buf.clone();
                let handle = tokio::spawn(async move {
                    let cmd = String::from_utf8(new_buf).expect("failed to parse cmd");
                    println!("{}", cmd);
                    run_process(cmd.as_str()).await.expect("failed to execute command")
                });

                let output = tokio::join!(handle);
                socket
                    .write_all(&buf[0..n])
                    .await
                    .expect("failed to write to socket");
            }
        });
    }

    Ok(())
}

// basic handler that responds with a static string
async fn help() -> &'static str {
    "Hello, World!"
}

/*
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {

    let handle = tokio::spawn(async move {
        let command = "ls".to_string();
        run_process(command.as_str()).await;
    });
    tokio::join!(handle);
    Ok(())
}
*/

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let handle = tokio::spawn(async move {
        run_tcp_server().await;
    });

    let app = route("/help", get(help));

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    hyper::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();

    Ok(())
}

运行上面这段代码, 通过执行

nc 127.0.0.1 18080

连接发送ls命令

会报下面这个错误

thread 'tokio-runtime-worker' panicked at 'failed to execute command: Error { kind: InvalidInput, message: "nul byte found in provided data" }', src/main.rs:56:53

但是如果我将

command.arg("-c").arg(std::ffi::OsStr::new(cmd.clone()));

替换成

command.arg("-c").arg("ls")

就可以正确拿到结果.

评论区

写评论
作者 liberwang1013 2021-08-14 10:49

确实可以了, 感谢

--
👇
Grobycn: 问题出在数据转换成字符串的过程,你用 let new_buf = buf[..n].to_vec(); 代替 let new_buf = buf.clone();

Grobycn 2021-08-13 15:26

问题出在数据转换成字符串的过程,你用 let new_buf = buf[..n].to_vec(); 代替 let new_buf = buf.clone();

1 共 2 条评论, 1 页