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")
就可以正确拿到结果.
1
共 2 条评论, 1 页
评论区
写评论确实可以了, 感谢
--
👇
Grobycn: 问题出在数据转换成字符串的过程,你用
let new_buf = buf[..n].to_vec();
代替let new_buf = buf.clone();
问题出在数据转换成字符串的过程,你用
let new_buf = buf[..n].to_vec();
代替let new_buf = buf.clone();