|
|
@ -10,7 +10,7 @@ use std::error::Error;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Read;
|
|
|
|
use std::io::Read;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::process::{Child, Command, ExitStatus};
|
|
|
|
use std::process::{Child, Command, ExitStatus, Stdio};
|
|
|
|
|
|
|
|
|
|
|
|
type SupResult<T> = Result<T, Box<dyn Error>>;
|
|
|
|
type SupResult<T> = Result<T, Box<dyn Error>>;
|
|
|
|
|
|
|
|
|
|
|
@ -36,24 +36,21 @@ impl App {
|
|
|
|
match command.output() {
|
|
|
|
match command.output() {
|
|
|
|
Ok(output) => {
|
|
|
|
Ok(output) => {
|
|
|
|
if !output.stdout.is_empty() {
|
|
|
|
if !output.stdout.is_empty() {
|
|
|
|
info!(
|
|
|
|
let s = String::from_utf8(output.stdout)?;
|
|
|
|
"[{}] stdout: {}",
|
|
|
|
for line in s.lines() {
|
|
|
|
&self.name,
|
|
|
|
info!("[{}] stdout: {}", &self.name, line);
|
|
|
|
String::from_utf8(output.stdout)?
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !output.stderr.is_empty() {
|
|
|
|
if !output.stderr.is_empty() {
|
|
|
|
info!(
|
|
|
|
let s = String::from_utf8(output.stderr)?;
|
|
|
|
"[{}] stderr: {}",
|
|
|
|
for line in s.lines() {
|
|
|
|
&self.name,
|
|
|
|
info!("[{}] stderr: {}", &self.name, line);
|
|
|
|
String::from_utf8(output.stderr)?
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => error!("Error starting app: {}: {:?}", &self.name, e),
|
|
|
|
Err(e) => Err(Box::from(e)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -85,12 +82,56 @@ impl Proc {
|
|
|
|
info!("starting application {}", &app.name);
|
|
|
|
info!("starting application {}", &app.name);
|
|
|
|
|
|
|
|
|
|
|
|
let mut command = Command::new(&app.command);
|
|
|
|
let mut command = Command::new(&app.command);
|
|
|
|
|
|
|
|
command.stdout(Stdio::piped());
|
|
|
|
|
|
|
|
command.stderr(Stdio::piped());
|
|
|
|
command.args(&app.args);
|
|
|
|
command.args(&app.args);
|
|
|
|
|
|
|
|
|
|
|
|
let child = command.spawn()?;
|
|
|
|
let child = command.spawn()?;
|
|
|
|
|
|
|
|
|
|
|
|
Ok(Proc { app, child })
|
|
|
|
Ok(Proc { app, child })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn check_stdout(&mut self) -> Option<String> {
|
|
|
|
|
|
|
|
let child_stdout = self.child.stdout.as_mut();
|
|
|
|
|
|
|
|
if let Some(stdout) = child_stdout {
|
|
|
|
|
|
|
|
let mut buf = String::new();
|
|
|
|
|
|
|
|
match stdout.read_to_string(&mut buf) {
|
|
|
|
|
|
|
|
Ok(size) => {
|
|
|
|
|
|
|
|
if size > 0 {
|
|
|
|
|
|
|
|
return Some(buf);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
|
|
error!("couldn't read stdout from {}: {:?}", &self.app.name, e);
|
|
|
|
|
|
|
|
return None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn check_stderr(&mut self) -> Option<String> {
|
|
|
|
|
|
|
|
let child_stderr = self.child.stderr.as_mut();
|
|
|
|
|
|
|
|
if let Some(stderr) = child_stderr {
|
|
|
|
|
|
|
|
let mut buf = String::new();
|
|
|
|
|
|
|
|
match stderr.read_to_string(&mut buf) {
|
|
|
|
|
|
|
|
Ok(size) => {
|
|
|
|
|
|
|
|
if size > 0 {
|
|
|
|
|
|
|
|
return Some(buf);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
|
|
error!("couldn't read stderr from {}: {:?}", &self.app.name, e);
|
|
|
|
|
|
|
|
return None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
fn main() {
|
|
|
@ -105,6 +146,7 @@ fn main() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[allow(clippy::cognitive_complexity)]
|
|
|
|
fn run() -> SupResult<()> {
|
|
|
|
fn run() -> SupResult<()> {
|
|
|
|
let config = Config::load("sup.toml")?;
|
|
|
|
let config = Config::load("sup.toml")?;
|
|
|
|
info!("loaded config: sup.toml");
|
|
|
|
info!("loaded config: sup.toml");
|
|
|
@ -159,12 +201,21 @@ fn run() -> SupResult<()> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(None) => {
|
|
|
|
Ok(None) => {
|
|
|
|
|
|
|
|
if let Some(s) = &proc.check_stdout() {
|
|
|
|
|
|
|
|
for line in s.lines() {
|
|
|
|
|
|
|
|
info!("[{}] stdout: {}", &proc.app.name, line);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(s) = &proc.check_stderr() {
|
|
|
|
|
|
|
|
for line in s.lines() {
|
|
|
|
|
|
|
|
info!("[{}] stderr: {}", &proc.app.name, line);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
newprocs.push(proc);
|
|
|
|
newprocs.push(proc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => error!("error: {:?}", e),
|
|
|
|
Err(e) => error!("error: {:?}", e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
procs = newprocs;
|
|
|
|
procs = newprocs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|