ant_core/node/process/
spawn.rs1use std::path::Path;
2use std::process::Stdio;
3
4use tokio::process::{Child, Command};
5
6use crate::error::{Error, Result};
7
8pub async fn spawn_node(
12 binary_path: &Path,
13 args: &[String],
14 env_vars: &[(String, String)],
15 log_dir: &Path,
16) -> Result<Child> {
17 tokio::fs::create_dir_all(log_dir)
18 .await
19 .map_err(|e| Error::ProcessSpawn(format!("Failed to create log directory: {e}")))?;
20
21 let stdout_path = log_dir.join("stdout.log");
22 let stderr_path = log_dir.join("stderr.log");
23
24 let stdout_file = std::fs::OpenOptions::new()
25 .create(true)
26 .append(true)
27 .open(&stdout_path)
28 .map_err(|e| Error::ProcessSpawn(format!("Failed to open stdout log: {e}")))?;
29 let stderr_file = std::fs::OpenOptions::new()
30 .create(true)
31 .append(true)
32 .open(&stderr_path)
33 .map_err(|e| Error::ProcessSpawn(format!("Failed to open stderr log: {e}")))?;
34
35 let mut cmd = Command::new(binary_path);
36 cmd.args(args)
37 .envs(env_vars.iter().map(|(k, v)| (k.as_str(), v.as_str())))
38 .stdin(Stdio::null())
39 .stdout(stdout_file)
40 .stderr(stderr_file)
41 .kill_on_drop(false);
44
45 #[cfg(windows)]
46 {
47 const CREATE_NO_WINDOW: u32 = 0x08000000;
48 cmd.creation_flags(CREATE_NO_WINDOW);
49 }
50
51 let child = cmd
52 .spawn()
53 .map_err(|e| Error::ProcessSpawn(format!("Failed to spawn node process: {e}")))?;
54
55 Ok(child)
56}