From 3fde1b40366a084f501a399a7972d4f4e149a877 Mon Sep 17 00:00:00 2001 From: Lifei Chen Date: Fri, 17 Dec 2021 11:21:38 +0800 Subject: [PATCH] feat: release for v0.1.16. (#10) Main feature includes: - Fix linux shell envs. - Fix bug of write output to tmp file. --- CHANGELOG.md | 7 +++ Cargo.lock | 2 +- Cargo.toml | 3 +- install/install.sh | 6 +-- src/executor/proc.rs | 2 +- src/executor/shell_command.rs | 89 ++++++++++++++++++++++++++++------- 6 files changed, 84 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d79df7f..0876cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog All notable changes to this project will be documented in this file. + +## [0.1.16] - 2021-12-09 + +### Changed + +- Fix bug of write output to tmp file. + ## [0.1.15] - 2021-12-05 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 10a956b..58e2ec3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2427,7 +2427,7 @@ dependencies = [ [[package]] name = "tat_agent" -version = "0.1.15" +version = "0.1.16" dependencies = [ "async-attributes", "async-std", diff --git a/Cargo.toml b/Cargo.toml index b7395b5..0498d38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tat_agent" -version = "0.1.15" +version = "0.1.16" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -45,7 +45,6 @@ users = { version = "0.11.0"} openssl = { version = '0.10.35', features = ["vendored"] } procfs = "0.11.0" - [target.'cfg(windows)'.dependencies] codepage-strings = "1.0.1" winapi = { version = "0.3", features = ["winsvc","winbase","winnt","stringapiset","winnls","wow64apiset","synchapi","namedpipeapi"] } diff --git a/install/install.sh b/install/install.sh index 7cba3de..a2527af 100755 --- a/install/install.sh +++ b/install/install.sh @@ -91,7 +91,7 @@ install() { elif has_sysvinit; then cp -f tat_agent_service /etc/init.d/ chmod 755 /etc/init.d/tat_agent_service - # TODO: uncomment following code after 0.1.14 is released. + # TODO: uncomment following code after 0.1.15 is released. # if test "${need_restart}" = true; then /etc/init.d/tat_agent_service restart # fi @@ -110,7 +110,7 @@ install() { fi fi else - # TODO: uncomment following code after 0.1.14 is released. + # TODO: uncomment following code after 0.1.15 is released. # if test "${need_restart}" = true; then echo "no proper daemon manager found, tat_agent can not auto start" PID=$(cat ${PID_FILE}) @@ -155,4 +155,4 @@ case $1 in *) install true ;; -esac \ No newline at end of file +esac diff --git a/src/executor/proc.rs b/src/executor/proc.rs index 210c445..9473263 100644 --- a/src/executor/proc.rs +++ b/src/executor/proc.rs @@ -599,7 +599,7 @@ mod tests { use std::fs::File; use std::io::Write; use std::time::{Duration, Instant, SystemTime}; - use std::{fs, thread}; + use std::fs; use log::info; use rand::distributions::Alphanumeric; diff --git a/src/executor/shell_command.rs b/src/executor/shell_command.rs index f9df837..63a3215 100755 --- a/src/executor/shell_command.rs +++ b/src/executor/shell_command.rs @@ -9,7 +9,7 @@ use std::time::Duration; use std::{env, fmt, io}; use crate::common::consts::PIPE_BUF_DEFAULT_SIZE; -use crate::executor::proc::{self, BaseCommand, MyCommand}; +use crate::executor::proc::{BaseCommand, MyCommand}; use crate::start_failed_err_info; use async_trait::async_trait; use libc; @@ -81,24 +81,40 @@ impl ShellCommand { } fn prepare_cmd(&self, user: User) -> Command { - let mut envs = HashMap::new(); + // find shell + let mut shell_path = cmd_path("bash"); + let (shell, login_init) = if shell_path.is_some() { + let login_init = ". ~/.bash_profile 2> /dev/null || . ~/.bashrc 2> /dev/null ; "; + ("bash", login_init) + } else { + shell_path = cmd_path("sh"); + ("sh", "") + }; + + //build envs + let mut envs = HashMap::::new(); + let shell_path = shell_path.unwrap(); + envs.insert("SHELL".to_string(), shell_path); match user.home_dir().to_str() { Some(dir) => { - envs.insert("HOME", dir); + envs.insert("HOME".to_string(), dir.to_string()); } None => {} }; - envs.insert("USER", self.base.username.as_str()); - envs.insert("LOGNAME", self.base.username.as_str()); - - let mut shell = "bash"; - let mut login_init = ". ~/.bash_profile 2> /dev/null || . ~/.bashrc 2> /dev/null ; "; - if !cmd_exists(shell) { - shell = "sh"; - login_init = ""; + envs.insert("USER".to_string(), self.base.username.clone()); + envs.insert("LOGNAME".to_string(), self.base.username.clone()); + envs.insert("USERNAME".to_string(), self.base.username.clone()); + + let etc_envs; + if let Ok(content) = std::fs::read_to_string("/etc/environment") { + etc_envs = load_envs(content); + for (key, value) in etc_envs.into_iter() { + envs.insert(key, value); + } }; - let entrypoint = format!("{}{}", login_init, self.base.cmd_path()); + //build comand + let entrypoint = format!("{}{}", login_init, self.base.cmd_path()); let mut cmd = Command::new(shell); cmd.args(&["-c", entrypoint.as_str()]) .uid(user.uid()) @@ -177,8 +193,8 @@ impl BaseCommand { let mut reader = BufReader::new(stdout.unwrap()); let mut byte_after_finish = 0; let proc = match Process::new(pid as i32) { - Ok(proc)=> proc, - Err(_)=> return , + Ok(proc) => proc, + Err(_) => return, }; loop { let process_finish = !proc.is_alive(); @@ -201,7 +217,7 @@ impl BaseCommand { let len = read_size.unwrap(); if len > 0 { - if let Err(e) = log_file.write(&buffer) { + if let Err(e) = log_file.write(&buffer[..len]) { error!("write output file fail: {:?}", e) } @@ -273,16 +289,43 @@ fn own_process_group() -> Result<(), io::Error> { } } -fn cmd_exists(cmd: &str) -> bool { +fn cmd_path(cmd: &str) -> Option { if let Ok(path) = env::var("PATH") { for p in path.split(":") { let p_str = format!("{}/{}", p, cmd); if Path::new(&p_str).exists() { - return true; + return Some(p_str); + } + } + } + None +} + +fn load_envs(content: String) -> HashMap { + let mut envs: HashMap = HashMap::new(); + let lines: Vec<&str> = content.split('\n').collect(); + for mut line in lines { + line = line.trim_start(); + if line.len() == 0 || line.starts_with("#") { + continue; + } + if line.starts_with("export ") { + line = &line[7..]; + } + let env_part: Vec<&str> = line.splitn(2, '=').collect(); + if env_part.len() == 2 { + let key = env_part[0].trim_start().to_string(); + let mut value = env_part[1].to_string(); + if value.starts_with('"') && value.ends_with('"') + || value.ends_with('\'') && value.starts_with('\'') + { + value.remove(0); + value.pop(); } + envs.insert(key, value); } } - false + envs } #[cfg(test)] @@ -299,4 +342,14 @@ mod tests { fn test_working_directory_exists() { assert_eq!(working_directory_exists("/etc"), true); } + + #[test] + fn test_load_envs() { + let content = "# \n B=b\n D=d=d\n C= \"x\n"; + let envs = load_envs(content.to_string()); + assert!(envs.keys().len() == 3); + assert!(envs.get("B").unwrap() == "b"); + assert!(envs.get("D").unwrap() == "d=d"); + assert!(envs.get("C").unwrap() == " \"x"); + } }