source: trunk/tssh/tssh @ 149

Last change on this file since 149 was 149, checked in by g7moreau, 6 years ago
  • Let sleep command do the tempo sum
File size: 7.4 KB
RevLine 
[125]1#!/bin/bash
2#
[126]3# 2014/03/26 Gabriel Moreau <Gabriel Moreau(A)univ-grenoble-alpes.fr> - Initial release
[125]4#
5# From http://hd-recording.at/dokuwiki/doku.php?id=linux:tmux#tssh
6
7# Clean when Ctrl^C
[144]8trap '[ -n "${base_path}" -a -d "/tmp/${base_path}" ] && rm -rf "/tmp/${base_path}"; exit 4;' QUIT INT TERM
[125]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
[128]28DEPENDS
[126]29   On Debian, you need the package
[128]30
[126]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
[128]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
[125]44AUTHOR
45   Gabriel Moreau
46
47COPYRIGHT
[147]48   Copyright (C) 2014-2018, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
[125]49   Licence : GNU GPL version 2 or later
50END_USAGE
51   }
52
[128]53export remote_command=''
[125]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 
[128]68while getopts "w:c:fvh" options
[125]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         ;;
[128]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         ;;
[125]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
[137]114   local default_mode=''
115
116   # set local mode
117   if echo $1 | grep -- ^--mode=
118   then
119      default_mode=$(echo $1 | grep -- ^--mode= | cut -f 2 -d '=')
120      shift
121   fi
122
[125]123   for host in $*
124   do
[137]125      local mode=${default_mode}
[138]126      local last_char="${host: -1}"
[125]127      if [ "${last_char}" == "-" -o "${last_char}" == "+" ]
128      then
129         mode="${last_char}"
130         host="${host:0:${#host}-1}"
131      fi
132
[133]133      # short host without login part if any
[138]134      local justhost=${host#*@}
[133]135     
[143]136      cluster=$(grep "^${justhost}\b" ${HOME}/.csshrc | cut -f 2 -d '=' | sed -e 's/^[[:space:]]*//;')
[125]137      if [ "${cluster}" == "" ]
138      then
[133]139         # just a host to scan and add
[139]140         if [ "${fast}" != 'yes' -a "${mode}" != '-' ]
[125]141         then
[133]142            # test if exists host
143            if host ${justhost} | grep -q 'not found'
[125]144            then
[142]145               [ "${verbose}" == 'yes' ] && echo "Warning: ${justhost} does not exists"
[125]146               continue
147            fi
[133]148            if ! nmap -p 22 -sT -PN ${justhost} | grep -q '\bopen\b'
[125]149            then
[133]150               if host ${justhost}.${dyn_domain} | grep -q 'not found' || ! nmap -p 22 -sT -PN ${justhost}.${dyn_domain} | grep -q '\bopen\b'
[125]151               then
[142]152                  [ "${verbose}" == 'yes' ] && echo "Warning: ${justhost} is down"
[125]153                  continue
154               else
[142]155                  [ "${verbose}" == 'yes' ] && echo "Warning: remove ssh key of ${justhost}.${dyn_domain}"
[133]156                  host=${justhost}.${dyn_domain}
157                  ssh-keygen -q -R $(LANG=C host ${justhost} | awk '{print $4}')
[125]158               fi
159            fi
160         fi
[142]161         [ "${verbose}" == 'yes' ] && echo "Warning: add ${host} on list with mode ${mode}"
[125]162         echo "${host}" >> "/tmp/${base_path}/master${mode}"
163      else
[133]164         # cluster, jump in a recursive mode
[142]165         [ "${verbose}" == 'yes' ] && echo "Warning: recursive call for cluster ${justhost} (${cluster}), with mode ${mode}"
[137]166         cluster=$(get_host_list --mode=${mode} "${cluster}")
[125]167      fi
168   done
169   }
170declare -fx get_host_list
171
172get_host_list $@
173cat "/tmp/${base_path}/master+" >> "/tmp/${base_path}/master"
174for f in $(grep . "/tmp/${base_path}/master-")
175do
176   egrep "^${f}$" "/tmp/${base_path}/master+" && continue
177   echo "${f}" >> "/tmp/${base_path}/master--"
178done
179for f in $(grep . "/tmp/${base_path}/master")
180do
181   egrep "^${f}$" "/tmp/${base_path}/master--" && continue
182   echo "${f}" >> "/tmp/${base_path}/master++"
183done
184
[134]185# split master list in paquet of split_number computer
186sort -u "/tmp/${base_path}/master++" | split -l ${split_number} - /tmp/${base_path}/__splitted_
[125]187
[148]188# wait is needed by time tmux session open and ssh time connection
189tempo=0.8
190first_tempo=0
191other_tempo=0
192if [ -n "${remote_command}" ]
193then
194   # add tempo after remote command
195   other_tempo=${tempo}
[149]196   first_tempo="${tempo} ${other_tempo}"
[148]197fi
198
[134]199# loop on each split windows
200for f in $(ls -1 /tmp/${base_path}/ | grep ^__splitted_)
[125]201do
[136]202   if [ "${verbose}" == 'yes' ]
203   then
[142]204      echo "Info: next hosts to be splitted"
[140]205      cat "/tmp/${base_path}/${f}" | sed -e 's/^/  /;'
[136]206      sleep 5
207   fi
208
[138]209   session=$(shuf -n 1 /usr/share/dict/words | tr -cd "[:alpha:]")
[125]210
211   IFS=$'\n' host=($(cat "/tmp/${base_path}/${f}"))
212
[148]213   tmux -2 new-session -d -s $session "ssh ${host[0]} ${remote_command}; sleep ${first_tempo}"
214   # wait ${tempo} second to let new session start...
215   sleep ${tempo}
[125]216
217   for (( i=1 ; i < ${#host[@]} ; i++))
218   do
[148]219      # wait ${tempo} needed in case of ${remote_command}
220      tmux splitw -t $session "ssh ${host[$i]} ${remote_command}; sleep ${other_tempo}"
[125]221      tmux select-layout tiled
222   done
223
224   tmux set-window-option synchronize-panes on  > /dev/null
225   tmux set-window-option -g utf8 on            > /dev/null
226   tmux set -g default-terminal screen-256color > /dev/null
227   #tmux set-option -g set-clipboard on
228 
229   # Sane scrolling
230   #tmux set -g mode-mouse on
231   #tmux set -g mouse-resize-pane on
232   #tmux set -g mouse-select-pane on
233   #tmux set -g mouse-select-window on
234 
235   #set -g terminal-overrides 'xterm*:smcup@:rmcup@'
236 
237   # toggle mouse mode to allow mouse copy/paste
238   # set mouse on with prefix m
239   tmux bind m \
240      set -g mode-mouse on \; \
241      set -g mouse-select-pane on \; \
242      display 'Mouse: ON' > /dev/null
243      # set -g mouse-resize-pane on \; \
244      #set -g mouse-select-window on \; \
245   # set mouse off with prefix M
246   tmux bind M \
247      set -g mode-mouse off \; \
248      set -g mouse-select-pane off \; \
249      display 'Mouse: OFF' > /dev/null
250      #set -g mouse-resize-pane off \; \
251      #set -g mouse-select-window off \; \
252   # toggle Broadcast
253   tmux bind b set-window-option synchronize-panes
254
255   tmux attach -t $session
256done
257
258# Clean temporary folder
259[ -d "/tmp/${base_path}" ] && rm -rf "/tmp/${base_path}"
Note: See TracBrowser for help on using the repository browser.