Everyday I connect to a number of servers, and everyday I send the same command to a list of servers.
Sometimes it is Ubuntu servers, sometimes Debian servers; I needed a way to slice and dice my list of servers, and start a clustered ssh session with the resulting sliced and diced list of servers.
Enter tmux, tmux-cssh, and some custom bash scripting.
So, a little while a go I switched to Windows as my daily desktop OS.
I figured out how to tune Windows Terminal to my liking, but was missing clusterssh from my OSX days.
A friend of mine (Shane Howearth), pointed me (I think he unknowingly pointed me) to tmux.
And in turn I was pointed to tmux-cssh
Very cool that this is written by a Kiwi (New Zealander).
So, tmux-cssh allows me to cluster my ssh sessions. Now I need to figure a way to slice and dice my list of servers.
The Problem
I have some Ubuntu servers, and some Debian servers.
Some of those servers are bare metal, some are not.
Some of those servers are Hyper Visors, some are not.
Sometimes I want to connect to only Debian servers, sometimes I want to connect to only real machines (bare metal installs).
I want the ability to organise my list of servers into some kind of searchable list.
My Solution
Firstly, I don’t know whether this is the most elegant way, in fact, I’m pretty sure it’s not, and I would love to hear people’s suggestions.
Comment below !
For this to work, you must have your ssh sorted.
i.e. you must be able to do:
Here is what I came up with:
The Data
I pictured my list of hosts as a number of rows in a table (or spreadsheet), and my “categories” as row headings.
Kind of like this:
hostname | debian_hosts | real_hosts | hv_hosts | ubuntu_hosts | mikrotik_hosts | blank |
---|---|---|---|---|---|---|
host1 | y | |||||
host2 | y | |||||
host3 | y | |||||
host4 | y | |||||
host5 | y | |||||
host6 | y | |||||
host7 | y | |||||
host8 | y | |||||
host9 | y | y | ||||
host10 | y | y | ||||
host11 | y | y | y | |||
host12 | y | y | ||||
host13 | y | y | ||||
host14 | y | |||||
host15 | y | y | ||||
host16 | y | |||||
host17 | y | |||||
host18 | y | |||||
host19 | y |
Weirdly, I had to create a blank column at the end.
Otherwise, bash would drop the last column.
So, now bash drops the blank column.
I saved this info into a csv file (input.csv).
The data is now “predictable”. 👍
Selecting from the data
awk to the rescue:
Let’s do a quick run down on awk:
- -v allows me to pass variables to awk.
- In this case I’m using it to name my columns.
- -F means fields are separated by the following character.
- in this case “,” as this is a csv (comma separated values) file.
- {print $1 } means, print the first column. i.e. the hostname.
Some Bash things I’ll use
So, I love bash.
I think anyone who reads this blog knows that ❗
I’m going to create an array I call “categories” using bash’s internal IFS special shell variable.
I’m also going to use getopt to get variables passed from the command line.
Basically, I want to use pretty short AND long variable names 😊
One interesting thing I’ll note here:
I wanted a “list” function that would list all my hosts, or list the hosts in a specific category.
My getopt options expect a passed argument.
i.e. options=$(getopt -o hdrvumal: --long help,debian,real,virtual,ubuntu,mikrotik,all,list: -- "$@")
So I wrote a wee bit in the script that checks to see if $arg2 is set, and if it’s not, then sets it, and also sets “default” values.
The Script
that’s enough chatter … here’s the script 😌
I’ve stored tmux-cssh in my ~/bin/ directory, and made sure it is executable.
Conclusion
Well, it works 👍
I’m not sure this is the “best” way of achieving what I wanted? I’d love to hear what you think.
1 Comment