use crate::process::Process;
use anyhow::{Context, Result};
use std::fs::OpenOptions;
use std::process::Command;
pub fn spawn(process: &Process) -> Result<u32> {
if let Some(parent) = process.log_out.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("Failed to create log directory {:?}", parent))?;
}
let log_out = OpenOptions::new()
.create(true)
.append(true)
.open(&process.log_out)
.with_context(|| format!("Failed to open stdout log {:?}", process.log_out))?;
let log_err = OpenOptions::new()
.create(true)
.append(true)
.open(&process.log_err)
.with_context(|| format!("Failed to open stderr log {:?}", process.log_err))?;
let child = Command::new("sh")
.arg("-c")
.arg(&process.command)
.current_dir(&process.cwd)
.envs(&process.env)
.stdout(log_out)
.stderr(log_err)
.stdin(std::process::Stdio::null())
.spawn()
.with_context(|| {
format!(
"Failed to spawn process '{}' with command: {}",
process.name, process.command
)
})?;
Ok(child.id())
}
pub fn stop(pid: u32) -> Result<()> {
if pid == 0 {
return Ok(());
}
let ret = unsafe { libc::kill(pid as libc::pid_t, libc::SIGTERM) };
if ret != 0 {
let err = std::io::Error::last_os_error();
if err.raw_os_error() == Some(libc::ESRCH) {
return Ok(());
}
return Err(anyhow::anyhow!("kill({}, SIGTERM) failed: {}", pid, err));
}
Ok(())
}
pub fn is_running(pid: u32) -> bool {
if pid == 0 {
return false;
}
unsafe { libc::kill(pid as libc::pid_t, 0) == 0 }
}