source: trunk/tssh/tssh @ 128

Last change on this file since 128 was 128, checked in by g7moreau, 7 years ago
  • Begin -c implementation (command)
File size: 6.0 KB
Line 
1#!/bin/bash
2#
3# 2014/03/26 Gabriel Moreau <Gabriel Moreau(A)univ-grenoble-alpes.fr> - Initial release
4#
5# From http://hd-recording.at/dokuwiki/doku.php?id=linux:tmux#tssh
6
7# Clean when Ctrl^C
8trap '[ -n "${base_path}" -a -d "/tmp/${base_path}" ] && rm -rf "/tmp/${base_path}"' QUIT
9
10export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
11export LANG=C
12
13
14function usage() {
15   cat <<END_USAGE
16NAME
17   $(basename $0) - tmux cluster ssh
18
19SYNOPSIS
20   $0 [-w number] [-f] [-v] <host1> <host2> <clusterssh class>... <hostM>- <hostN>+
21
22OPTIONS
23   -w  windows to open (integer, default 16)
24   -f  fast, no nmap scan to eliminate sleeping computer
25   -v  verbose
26   -h  help
27
28DEPENDS
29   On Debian, you need the package
30
31    apt-get install tmux ncurses-bin wamerican nmap
32
33   wamerican (or wfrench...) is used to choose a random word in the file /usr/share/dict/words
34   for each new tmux session.
35   ncurses-bin is required for the tput command
36   to automatically split your terminal into several small panels.
37   nmap is only used for dynamic DNS domain and dynamic scan.
38   This is not mandatory for general use.
39
40   By default, tssh use tput to know the number of columns and lines of your terminal.
41   It takes 10 lines and 40 columns for each windows by default.
42   If tput is not installed, the default is 16 windows...
43
44AUTHOR
45   Gabriel Moreau
46
47COPYRIGHT
48   Copyright (C) 2014-2017, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
49   Licence : GNU GPL version 2 or later
50END_USAGE
51   }
52
53export remote_command=''
54export split_number=16
55if which tput > /dev/null
56then
57   export split_number=$(( ($(tput  lines)/ 10) * ($(tput  cols)/ 40) ))
58fi
59
60export dyn_domain=''
61if [ -e "${HOME}/.tsshrc" ]
62then
63   . "${HOME}/.tsshrc"
64fi
65
66# get options
67if [ $# -eq 0 ]; then usage; exit 1; fi 
68while getopts "w:c:fvh" options
69do
70   case ${options} in
71      w)
72         if echo ${OPTARG} | egrep -q '^[[:digit:]]+$' && [ ${OPTARG} -gt 0 ]
73         then
74            export split_number=${OPTARG}
75         else
76            usage
77            exit 2
78         fi
79         ;;
80      c)
81         if echo ${OPTARG} | egrep -q '[[:alpha:]]'
82         then
83            export remote_command=${OPTARG}
84         else
85            usage
86            exit 2
87         fi
88         ;;
89      f)
90         export fast='yes'
91         ;;
92      v)
93         export verbose='yes'
94         ;;
95      h|*)
96         usage
97         exit 3
98         ;;
99   esac
100done
101shift $((OPTIND - 1))
102[[ $1 = "--" ]] && shift
103
104cd /tmp/
105export base_path=$(mktemp -d tssh.XXXXXX)
106touch "/tmp/${base_path}/master"
107touch "/tmp/${base_path}/master-"
108touch "/tmp/${base_path}/master+"
109touch "/tmp/${base_path}/master--"
110touch "/tmp/${base_path}/master++"
111
112get_host_list () {
113   local cluster
114   for host in $*
115   do
116      mode=""
117      last_char="${host: -1}"
118      if [ "${last_char}" == "-" -o "${last_char}" == "+" ]
119      then
120         mode="${last_char}"
121         host="${host:0:${#host}-1}"
122      fi
123
124      cluster=$(grep "^${host}" ${HOME}/.csshrc | cut -f 2 -d '=')
125      if [ "${cluster}" == "" ]
126      then
127         if [ "${fast}" != 'yes' ]
128         then
129            # short host without login part if any
130            if host ${host#*@} | grep -q 'not found'
131            then
132               [ "${verbose}" == "yes" ] && echo Warning: ${host#*@} does not exists
133               continue
134            fi
135            if ! nmap -p 22 -sT -PN ${host#*@} | grep -q '\bopen\b'
136            then
137               if host ${host#*@}.${dyn_domain} | grep -q 'not found' || ! nmap -p 22 -sT -PN ${host#*@}.${dyn_domain} | grep -q '\bopen\b'
138               then
139                  [ "${verbose}" == "yes" ] && echo Warning: ${host#*@} is down
140                  continue
141               else
142                  host=${host}.${dyn_domain}
143                  ssh-keygen -q -R $(LANG=C host ${host} | awk '{print $4}')
144               fi
145            fi
146         fi
147         echo "${host}" >> "/tmp/${base_path}/master${mode}"
148      else
149         cluster=$(get_host_list "${cluster}${mode}")
150      fi
151   done
152   }
153declare -fx get_host_list
154
155get_host_list $@
156cat "/tmp/${base_path}/master+" >> "/tmp/${base_path}/master"
157for f in $(grep . "/tmp/${base_path}/master-")
158do
159   egrep "^${f}$" "/tmp/${base_path}/master+" && continue
160   echo "${f}" >> "/tmp/${base_path}/master--"
161done
162for f in $(grep . "/tmp/${base_path}/master")
163do
164   egrep "^${f}$" "/tmp/${base_path}/master--" && continue
165   echo "${f}" >> "/tmp/${base_path}/master++"
166done
167
168sort -u "/tmp/${base_path}/master++" | split -l ${split_number} - /tmp/${base_path}/_
169
170for f in $(ls -1 /tmp/${base_path}/ | grep -v ^master)
171do
172   session=$(shuf -n 1 /usr/share/dict/words | tr -cd "[:alpha:]")
173
174   IFS=$'\n' host=($(cat "/tmp/${base_path}/${f}"))
175
176   tmux -2 new-session -d -s $session "ssh ${host[0]} ${remote_command}"
177
178
179   for (( i=1 ; i < ${#host[@]} ; i++))
180   do
181      tmux splitw -t $session "ssh ${host[$i]} ${remote_command}"
182      tmux select-layout tiled
183   done
184
185   tmux set-window-option synchronize-panes on  > /dev/null
186   tmux set-window-option -g utf8 on            > /dev/null
187   tmux set -g default-terminal screen-256color > /dev/null
188   #tmux set-option -g set-clipboard on
189 
190   # Sane scrolling
191   #tmux set -g mode-mouse on
192   #tmux set -g mouse-resize-pane on
193   #tmux set -g mouse-select-pane on
194   #tmux set -g mouse-select-window on
195 
196   #set -g terminal-overrides 'xterm*:smcup@:rmcup@'
197 
198   # toggle mouse mode to allow mouse copy/paste
199   # set mouse on with prefix m
200   tmux bind m \
201      set -g mode-mouse on \; \
202      set -g mouse-select-pane on \; \
203      display 'Mouse: ON' > /dev/null
204      # set -g mouse-resize-pane on \; \
205      #set -g mouse-select-window on \; \
206   # set mouse off with prefix M
207   tmux bind M \
208      set -g mode-mouse off \; \
209      set -g mouse-select-pane off \; \
210      display 'Mouse: OFF' > /dev/null
211      #set -g mouse-resize-pane off \; \
212      #set -g mouse-select-window off \; \
213   # toggle Broadcast
214   tmux bind b set-window-option synchronize-panes
215
216   tmux attach -t $session
217done
218
219# Clean temporary folder
220[ -d "/tmp/${base_path}" ] && rm -rf "/tmp/${base_path}"
Note: See TracBrowser for help on using the repository browser.