mirror of
https://github.com/house-of-vanity/rexec.git
synced 2025-07-08 09:14:08 +00:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
c699bf1849 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1 @@
|
||||
target
|
||||
pkg
|
||||
*zst
|
||||
|
@ -6,12 +6,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [1.0.4] - 2023-08-14
|
||||
|
||||
### Changed
|
||||
|
||||
- Expansion host strings.
|
||||
|
||||
## [1.0.1] - 2023-06-20
|
||||
|
||||
### Changed
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1043,7 +1043,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||
|
||||
[[package]]
|
||||
name = "rexec"
|
||||
version = "1.0.4"
|
||||
version = "1.0.2"
|
||||
dependencies = [
|
||||
"brace-expand",
|
||||
"clap 4.3.4",
|
||||
|
@ -1,7 +1,6 @@
|
||||
[package]
|
||||
name = "rexec"
|
||||
version = "1.0.5"
|
||||
readme = "https://github.com/house-of-vanity/rexec#readme"
|
||||
version = "1.0.2"
|
||||
edition = "2021"
|
||||
description = "Parallel SSH executor"
|
||||
repository = "https://github.com/house-of-vanity/rexec"
|
||||
|
25
PKGBUILD
25
PKGBUILD
@ -1,25 +0,0 @@
|
||||
# Maintainer: AB <gh@hexor.ru>
|
||||
pkgname=rexec
|
||||
pkgver=1.0.4.r0.g3cf1e79
|
||||
pkgrel=1
|
||||
pkgdesc="Parallel SSH executor"
|
||||
url="https://github.com/house-of-vanity/rexec"
|
||||
license=("WTFPL")
|
||||
arch=("x86_64")
|
||||
makedepends=("cargo")
|
||||
|
||||
pkgver() {
|
||||
(git describe --long --tags || echo "$pkgver") | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
|
||||
}
|
||||
|
||||
build() {
|
||||
return 0
|
||||
}
|
||||
|
||||
package() {
|
||||
cd ..
|
||||
usrdir="$pkgdir/usr"
|
||||
mkdir -p $usrdir
|
||||
cargo install --no-track --path . --root "$usrdir"
|
||||
}
|
||||
|
99
src/main.rs
99
src/main.rs
@ -24,17 +24,13 @@ struct Args {
|
||||
#[arg(short, long, default_value_t = whoami::username())]
|
||||
username: String,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Use known_hosts to build servers list instead of string expansion."
|
||||
)]
|
||||
#[arg(short, long, help = "Use known_hosts to build servers list")]
|
||||
known_hosts: bool,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "Expression to build server list. List and range expansion are supported. Example: 'web-[1:12]-io-{prod,dev}'"
|
||||
help = "Expression to build server list. List and range expansion available. Example: 'web-[1:12]-io-{prod,dev}'"
|
||||
)]
|
||||
expression: String,
|
||||
|
||||
@ -81,59 +77,48 @@ fn read_known_hosts() -> Vec<Host> {
|
||||
result
|
||||
}
|
||||
|
||||
fn expand_range(start: i32, end: i32) -> Vec<String> {
|
||||
(start..=end).map(|i| i.to_string()).collect()
|
||||
}
|
||||
|
||||
fn expand_list(list: &str) -> Vec<String> {
|
||||
list.split(',').map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
fn expand_string(s: &str) -> Vec<Host> {
|
||||
fn expand_string(string: String) -> Vec<Host> {
|
||||
let mut result: Vec<String> = Vec::new();
|
||||
let mut _result: Vec<String> = Vec::new();
|
||||
let mut hosts: Vec<Host> = Vec::new();
|
||||
let mut result = vec![s.to_string()];
|
||||
|
||||
while let Some(r) = result.iter().find(|s| s.contains('[')) {
|
||||
let r = r.clone();
|
||||
let start = r.find('[').unwrap();
|
||||
let end = match r[start..].find(']') {
|
||||
None => {
|
||||
error!("Error parsing host expression. Wrong range expansion '[a:b]'");
|
||||
process::exit(1);
|
||||
if let Some(open_bracket_index) = string.find('[') {
|
||||
if let Some(close_bracket_index) = string.find(']') {
|
||||
let prefix = &string[..open_bracket_index];
|
||||
let range = &string[open_bracket_index + 1..close_bracket_index];
|
||||
let postfix = &string[close_bracket_index + 1..];
|
||||
|
||||
let parts: Vec<&str> = range.split(':').collect();
|
||||
|
||||
if parts.len() == 2 {
|
||||
if let Ok(start) = parts[0].parse::<u32>() {
|
||||
if let Ok(end) = parts[1].parse::<u32>() {
|
||||
for num in start..=end {
|
||||
_result.push(format!("{}{}{}", prefix, num, postfix));
|
||||
}
|
||||
Some(s) => s + start,
|
||||
};
|
||||
let colon = match r[start..end].find(':') {
|
||||
None => {
|
||||
error!("Error parsing host expression. Missing colon in range expansion '[a:b]'");
|
||||
process::exit(1);
|
||||
}
|
||||
Some(c) => c + start,
|
||||
};
|
||||
let low = r[start + 1..colon].parse::<i32>().unwrap();
|
||||
let high = r[colon + 1..end].parse::<i32>().unwrap();
|
||||
result.retain(|s| s != &r);
|
||||
for val in expand_range(low, high) {
|
||||
let new_str = format!("{}{}{}", &r[..start], val, &r[end + 1..]);
|
||||
result.push(new_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_result.push(String::from(string));
|
||||
}
|
||||
|
||||
while let Some(r) = result.iter().find(|s| s.contains('{')) {
|
||||
let r = r.clone();
|
||||
let start = r.find('{').unwrap();
|
||||
let end = match r.find('}') {
|
||||
None => {
|
||||
error!("Error parsing host expression. Wrong range expansion '{{one,two}}'");
|
||||
process::exit(1);
|
||||
for string in _result {
|
||||
if let Some(open_brace_index) = string.find('{') {
|
||||
if let Some(close_brace_index) = string.find('}') {
|
||||
let prefix = &string[..open_brace_index];
|
||||
let list = &string[open_brace_index + 1..close_brace_index];
|
||||
let postfix = &string[close_brace_index + 1..];
|
||||
|
||||
let items: Vec<&str> = list.split(',').collect();
|
||||
|
||||
for item in items {
|
||||
result.push(format!("{}{}{}", prefix, item, postfix));
|
||||
}
|
||||
Some(s) => s,
|
||||
};
|
||||
let list = &r[start + 1..end];
|
||||
result.retain(|s| s != &r);
|
||||
for val in expand_list(list) {
|
||||
let new_str = format!("{}{}{}", &r[..start], val, &r[end + 1..]);
|
||||
result.push(new_str);
|
||||
}
|
||||
} else {
|
||||
result.push(String::from(string));
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +156,7 @@ fn main() {
|
||||
.collect()
|
||||
} else {
|
||||
info!("Using string expansion to build server list.");
|
||||
expand_string(&args.expression)
|
||||
expand_string(args.expression)
|
||||
};
|
||||
|
||||
// Dedup hosts from known_hosts file
|
||||
@ -180,16 +165,6 @@ fn main() {
|
||||
// Build MasshHostConfig hostnames list
|
||||
let mut massh_hosts: Vec<MasshHostConfig> = vec![];
|
||||
let mut hosts_and_ips: HashMap<IpAddr, String> = HashMap::new();
|
||||
if args.parallel != 100 {
|
||||
warn!("Parallelism: {} thread{}", &args.parallel, {
|
||||
if args.parallel != 1 {
|
||||
"s."
|
||||
} else {
|
||||
"."
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
info!("Matched hosts:");
|
||||
for host in matched_hosts.iter() {
|
||||
let ip = match lookup_host(&host.name) {
|
||||
|
Reference in New Issue
Block a user