mirror of
https://github.com/Noratrieb/service-manager.git
synced 2026-01-14 16:35:05 +01:00
works.
This commit is contained in:
parent
072deb19c1
commit
4a9990a9cd
4 changed files with 56 additions and 68 deletions
|
|
@ -4,10 +4,9 @@ use crate::{view, App};
|
||||||
use crossterm::event;
|
use crossterm::event;
|
||||||
use crossterm::event::{Event, KeyCode};
|
use crossterm::event::{Event, KeyCode};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::OsString;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{ErrorKind, Read};
|
use std::io::{ErrorKind, Read, Write};
|
||||||
use std::os::unix::ffi::OsStrExt;
|
|
||||||
use std::process::{Child, Command, Stdio};
|
use std::process::{Child, Command, Stdio};
|
||||||
use std::sync::mpsc::TryRecvError;
|
use std::sync::mpsc::TryRecvError;
|
||||||
use std::sync::{mpsc, Mutex};
|
use std::sync::{mpsc, Mutex};
|
||||||
|
|
@ -15,6 +14,10 @@ use tui::backend::Backend;
|
||||||
use tui::widgets::TableState;
|
use tui::widgets::TableState;
|
||||||
use tui::Terminal;
|
use tui::Terminal;
|
||||||
|
|
||||||
|
const STDOUT_SEND_BUF_SIZE: usize = 512;
|
||||||
|
|
||||||
|
pub type StdoutSendBuf = ([u8; STDOUT_SEND_BUF_SIZE], usize);
|
||||||
|
|
||||||
pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<()> {
|
pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
terminal.draw(|f| view::render_ui(f, &mut app))?;
|
terminal.draw(|f| view::render_ui(f, &mut app))?;
|
||||||
|
|
@ -64,7 +67,7 @@ impl App {
|
||||||
.or_else(|_| std::env::current_dir())?,
|
.or_else(|_| std::env::current_dir())?,
|
||||||
env: service.env.unwrap_or_else(HashMap::new),
|
env: service.env.unwrap_or_else(HashMap::new),
|
||||||
status: Mutex::new(ServiceStatus::NotStarted),
|
status: Mutex::new(ServiceStatus::NotStarted),
|
||||||
stdout_buf: OsString::new(),
|
stdout_buf: Vec::new(),
|
||||||
stdout_recv,
|
stdout_recv,
|
||||||
stdout_send: Mutex::new(Some(stdout_send)),
|
stdout_send: Mutex::new(Some(stdout_send)),
|
||||||
})
|
})
|
||||||
|
|
@ -82,19 +85,19 @@ impl App {
|
||||||
|
|
||||||
fn recv_stdouts(&mut self) {
|
fn recv_stdouts(&mut self) {
|
||||||
for service in self.table.services.iter_mut() {
|
for service in self.table.services.iter_mut() {
|
||||||
while let Ok(vec) = service.stdout_recv.try_recv() {
|
while let Ok((buf, n)) = service.stdout_recv.try_recv() {
|
||||||
service.stdout_buf.push(OsStr::from_bytes(&vec));
|
service.stdout_buf.extend_from_slice(&buf[0..n]);
|
||||||
|
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
format!(
|
format!(
|
||||||
"debug/received_something_{}_{}.txt",
|
"debug/received_something_{}_{}.txt",
|
||||||
service.name,
|
&service.name,
|
||||||
std::time::SystemTime::now()
|
std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_millis()
|
.as_millis()
|
||||||
),
|
),
|
||||||
service.stdout_buf.as_bytes(),
|
&service.stdout_buf,
|
||||||
)
|
)
|
||||||
.expect("debug failed fuck");
|
.expect("debug failed fuck");
|
||||||
}
|
}
|
||||||
|
|
@ -172,8 +175,13 @@ impl App {
|
||||||
|
|
||||||
let child = match cmd.spawn() {
|
let child = match cmd.spawn() {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
let mut buf = [0; STDOUT_SEND_BUF_SIZE];
|
||||||
|
|
||||||
|
let bytes = err.to_string();
|
||||||
|
(&mut buf[..]).write_all(bytes.as_bytes()).expect("dont");
|
||||||
|
|
||||||
stdout_send
|
stdout_send
|
||||||
.send(err.to_string().into_bytes())
|
.send((buf, bytes.len()))
|
||||||
.expect("failed to send stdout");
|
.expect("failed to send stdout");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +200,7 @@ impl App {
|
||||||
}
|
}
|
||||||
fn child_process_thread(
|
fn child_process_thread(
|
||||||
child: Child,
|
child: Child,
|
||||||
stdout_send: mpsc::Sender<Vec<u8>>,
|
stdout_send: mpsc::Sender<StdoutSendBuf>,
|
||||||
terminate_channel: mpsc::Receiver<()>,
|
terminate_channel: mpsc::Receiver<()>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut child = child;
|
let mut child = child;
|
||||||
|
|
@ -204,29 +212,30 @@ fn child_process_thread(
|
||||||
Err(TryRecvError::Empty) => {}
|
Err(TryRecvError::Empty) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stdout_buf = Vec::new();
|
let mut stdout_buf = [0; STDOUT_SEND_BUF_SIZE];
|
||||||
|
|
||||||
match stdout.read(&mut stdout_buf) {
|
match stdout.read(&mut stdout_buf) {
|
||||||
Ok(0) => continue,
|
Ok(0) => continue,
|
||||||
Ok(_) => {
|
Ok(n) => {
|
||||||
std::fs::write(
|
// std::fs::write(
|
||||||
format!(
|
// format!(
|
||||||
"debug/read_something_{}.txt",
|
// "debug/read_something_{}.txt",
|
||||||
std::time::SystemTime::now()
|
// std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
// .duration_since(std::time::UNIX_EPOCH)
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.as_millis()
|
// .as_millis()
|
||||||
),
|
// ),
|
||||||
&stdout_buf,
|
// &stdout_buf,
|
||||||
)
|
// )
|
||||||
.ok();
|
// .ok();
|
||||||
|
|
||||||
|
stdout_send
|
||||||
|
.send((stdout_buf, n))
|
||||||
|
.map_err(|_| io::Error::from(io::ErrorKind::Other))?;
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
|
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
stdout_send
|
|
||||||
.send(stdout_buf)
|
|
||||||
.map_err(|_| io::Error::from(io::ErrorKind::Other))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match child.kill() {
|
match child.kill() {
|
||||||
|
|
|
||||||
37
src/main.rs
37
src/main.rs
|
|
@ -18,43 +18,6 @@ use crate::model::config::Config;
|
||||||
use crate::model::App;
|
use crate::model::App;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
///// ------------------------ TEST START ------------------------
|
|
||||||
|
|
||||||
let mut cmd = std::process::Command::new("sh");
|
|
||||||
|
|
||||||
let mut child = cmd
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.args(&["-c", "echo hello"])
|
|
||||||
.spawn()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut stdout = child.stdout.take().unwrap(); // std::fs::File::open("config.toml").unwrap();
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
let mut buf = [0; 1024];
|
|
||||||
|
|
||||||
println!("{}", buf.len());
|
|
||||||
|
|
||||||
// stdout.read_to_end(&mut buf);
|
|
||||||
|
|
||||||
// println!("{}", String::from_utf8_lossy(&buf).as_ref());
|
|
||||||
|
|
||||||
// return;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match stdout.read(&mut buf) {
|
|
||||||
Ok(0) => break,
|
|
||||||
Ok(_) => println!("READ: now `{}`", String::from_utf8(buf.to_vec()).unwrap()),
|
|
||||||
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
|
|
||||||
Err(e) => eprintln!("error: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("done!");
|
|
||||||
});
|
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_secs(3454233));
|
|
||||||
|
|
||||||
///// ------------------------ TEST END ------------------------
|
|
||||||
|
|
||||||
let file_path = env::args()
|
let file_path = env::args()
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.or_else(|| env::var("SERVICE_MANAGER_CONFIG_PATH").ok())
|
.or_else(|| env::var("SERVICE_MANAGER_CONFIG_PATH").ok())
|
||||||
|
|
|
||||||
22
src/model.rs
22
src/model.rs
|
|
@ -1,5 +1,8 @@
|
||||||
|
use crate::controller::StdoutSendBuf;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Error;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{mpsc, Mutex};
|
use std::sync::{mpsc, Mutex};
|
||||||
use tui::widgets::TableState;
|
use tui::widgets::TableState;
|
||||||
|
|
@ -24,9 +27,9 @@ pub struct Service {
|
||||||
pub workdir: PathBuf,
|
pub workdir: PathBuf,
|
||||||
pub env: HashMap<String, String>,
|
pub env: HashMap<String, String>,
|
||||||
pub status: Mutex<ServiceStatus>,
|
pub status: Mutex<ServiceStatus>,
|
||||||
pub stdout_buf: OsString,
|
pub stdout_buf: Vec<u8>,
|
||||||
pub stdout_recv: mpsc::Receiver<Vec<u8>>,
|
pub stdout_recv: mpsc::Receiver<StdoutSendBuf>,
|
||||||
pub stdout_send: Mutex<Option<mpsc::Sender<Vec<u8>>>>,
|
pub stdout_send: Mutex<Option<mpsc::Sender<StdoutSendBuf>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -52,3 +55,16 @@ pub mod config {
|
||||||
pub env: Option<HashMap<String, String>>,
|
pub env: Option<HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type SmResult = Result<(), SmError>;
|
||||||
|
|
||||||
|
pub enum SmError {
|
||||||
|
Io(io::Error),
|
||||||
|
MutexPoisoned,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for SmError {
|
||||||
|
fn from(e: Error) -> Self {
|
||||||
|
Self::Io(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ fn render_full_view<B: Backend>(f: &mut Frame<B>, state: &mut AppState, index: u
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.title("service".as_ref());
|
.title("service".as_ref());
|
||||||
|
|
||||||
let stdout = service.stdout_buf.to_string_lossy();
|
let stdout = String::from_utf8_lossy(&service.stdout_buf);
|
||||||
|
|
||||||
let paragraph = Paragraph::new(stdout.as_ref()).block(block);
|
let paragraph = Paragraph::new(stdout.as_ref()).block(block);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue