bin/i2cssh in i2cssh-1.12.0 vs bin/i2cssh in i2cssh-1.13.0
- old
+ new
@@ -1,58 +1,78 @@
-#!/usr/bin/ruby
+#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'i2cssh'
require 'yaml'
@config_file = File.expand_path "~/.i2csshrc"
-@i2_options, ssh_options, @servers, @clusters, @ssh_environment, opts_from_cmdline = {}, [], [], {}, {}, {}
+@i2_options, ssh_options, @servers, @clusters, @ssh_environment, opts_from_cmdline = [], [], [], {}, [], {}
def get_hosts(c)
- if c =~ /(.+)@(.+)/ then
- login_from_cli = $1
- c = $2
- end
+ c.each do |clus|
- cluster = @clusters[c]
+ if clus =~ /(.+)@(.+)/
+ login_from_cli = $1
+ clus = $2
+ end
- if cluster
- set_options(cluster, login_from_cli)
+ cluster = @clusters[clus]
+ if cluster
+ set_options(cluster, login_from_cli)
- if @i2_options[:login] then
- @servers += cluster["hosts"].map{|h| "#{@i2_options[:login]}@#{h}"}
+ if @i2_options.last[:login]
+ @servers << cluster["hosts"].map{|h| "#{@i2_options.last[:login]}@#{h}"}
+ else
+ @servers << cluster["hosts"]
+ end
else
- @servers += cluster["hosts"]
+ puts "ERROR: unknown cluster #{c}. Check your #{@config_file}"
+ exit 1
end
- else
- puts "ERROR: unknown cluster #{c}. Check your #{@config_file}"
- exit 1
end
+
end
def set_options(config_hash, login_override=nil)
- if config_hash["columns"] and config_hash["rows"] then
+ if config_hash["columns"] and config_hash["rows"]
puts "CONFIG ERROR: rows and columns can't be used at the same time"
exit 1
end
+
+ if @i2_options.size == 0
+ @i2_options << {}
+ else
+ # The first member includes the default options from the conf file
+ @i2_options << @i2_options.first.clone
+ end
[:broadcast, :profile, :rank, :iterm2, :login, :columns, :rows, :sleep, :direction, :itermname].each do |p|
- @i2_options[p] = config_hash[p.to_s].nil? ? @i2_options[p] : config_hash[p.to_s]
+ @i2_options.last[p] = config_hash[p.to_s].nil? ? @i2_options.last[p] : config_hash[p.to_s]
end
+
+ @i2_options.last[:login] = login_override if login_override
+ @i2_options.last[:direction] ||= :column
+ @i2_options.last[:direction] = @i2_options.last[:direction].to_sym
+ if config_hash["environment"]
+ if @ssh_environment.empty?
+ @ssh_environment << {}
+ else
+ # We have some global env so copy it
+ @ssh_environment << @ssh_environment.first.clone
+ end
- @i2_options[:login] = login_override if login_override
- @i2_options[:direction] ||= :column
- @i2_options[:direction] = @i2_options[:direction].to_sym
- @ssh_environment.merge!(config_hash["environment"].inject({}){|m, v| m.merge(v)}) if config_hash["environment"]
+ @ssh_environment.last.merge!(config_hash["environment"].inject({}){|m, v| m.merge(v)})
+ end
+
end
if File.exists?(@config_file)
config_hash = YAML.load File.read @config_file
# Read config and set defaults from config
- if config_hash["version"] && config_hash["version"].to_i >= 2 then
+ if config_hash["version"] && config_hash["version"].to_i >= 2
set_options(config_hash)
@clusters = config_hash["clusters"]
else
# Convert version 1 format to version 2
@clusters = config_hash["clusters"].inject({}){|m, c| m[c[0]] = {"hosts" => c[1]}; m}
@@ -60,56 +80,88 @@
else
set_options({})
end
+
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename(__FILE__)} [options] [(username@host [username@host] | username@cluster)]"
# Check if we have a cluster.
- opts.on '-c', '--cluster CLUSTERNAME',
- 'Name of the cluster specified in ~/.i2csshrc' do |c|
+ opts.on '-c', '--clusters clus1,clus2', Array,
+ 'Comma-separated list of clusters specified in ~/.i2csshrc' do |c|
get_hosts(c)
end
+
opts.on '-m', '--machines a,b,c', Array,
'Comma-separated list of hosts' do |h|
- @servers += h
+
+ # Add to servers array and get a clone of default options
+ @servers << h
+ @i2_options << @i2_options.first.clone
+ if @ssh_environment.empty?
+ @ssh_environment << {}
+ else
+ @ssh_environment << @ssh_environment.first.clone
+ end
end
# Hosts
opts.on '-f', '--file FILE',
'Cluster file (one hostname per line)' do |f|
- @servers += File.read(f).split "\n"
+ @servers << File.read(f).split("\n")
+ @i2_options << @i2_options.first.clone
+ if @ssh_environment.empty?
+ @ssh_environment << {}
+ else
+ @ssh_environment << @ssh_environment.first.clone
+ end
end
+ opts.on '-t', '--tab-split',
+ 'Split servers/clusters into tabs (group arguments)' do
+ opts_from_cmdline[:tabs] = true
+ end
+
+ opts.on '-T', '--tab-split-nogroup',
+ 'Split servers/clusters into tabs (don\'t group arguments)' do
+ opts_from_cmdline[:tabs] = true
+ opts_from_cmdline[:tabs_nogroup] = true
+ end
+
# Command line options override config file
# SSH options
opts.on '-A', '--forward-agent',
'Enable SSH agent forwarding' do
ssh_options << '-A'
end
+
opts.on '-l', '--login LOGIN',
'SSH login name' do |u|
opts_from_cmdline[:login] = u
end
+
opts.on '-e', '--environment KEY=VAL',
'Send environment vars (comma-separated list, need to start with LC_)' do |e|
- @ssh_environment = e.split(",").inject({}) {|m, x| key, val = x.split("="); m[key] = val; m}
+ #Overwrite global ssh environment from config file
+ @ssh_environment[0] = e.split(",").inject({}) {|m, x| key, val = x.split("="); m[key] = val; m}
end
+
opts.on '-r', '--rank',
'Send LC_RANK with the host number as environment variable' do
opts_from_cmdline[:rank] = true
end
# iTerm2 options
opts.on '-F', '--fullscreen',
'Make the window fullscreen' do
opts_from_cmdline[:fullscreen] = true
end
+
opts.on '-C', '--columns COLUMNS', Integer,
'Number of columns (rows will be calculated)' do |c|
if opts_from_cmdline[:rows]
puts "ERROR: -C and -R can't be used at the same time"
puts optparse.help
@@ -152,11 +204,11 @@
'Number of seconds to sleep between creating SSH sessions' do |s|
opts_from_cmdline[:sleep] = s
end
opts.on "-d", '--direction DIRECTION', String,
'Direction that new sessions are created (default: column)' do |d|
- unless ["row", "column"].include?(d) then
+ unless ["row", "column"].include?(d)
puts "ERROR: -d requires 'row' or 'column'"
puts optparse.help
exit 1
end
opts_from_cmdline[:direction] = d.to_sym
@@ -168,21 +220,67 @@
end
end
optparse.parse!
-if ARGV.length == 1 then
- c = ARGV[0]
+if opts_from_cmdline[:tabs]
+ puts 'Disabling broadcast for tab split mode...'
+ opts_from_cmdline[:broadcast] = false
+end
+
+# One argument = one cluster
+if ARGV.length == 1
+ c = [ARGV[0]]
get_hosts(c)
-elsif ARGV.length > 1 then
- @servers = ARGV
+
+# Otherwise we have a list of hosts
+elsif ARGV.length > 1
+ if opts_from_cmdline[:tabs_nogroup]
+ ARGV.each do |serv|
+ @servers << [serv]
+ if @i2_options.size > 1 # We added stuff in with cmdline options
+ @i2_options << @i2_options.first.clone
+ if @ssh_environment.empty?
+ @ssh_environment << {}
+ else
+ @ssh_environment << @ssh_environment.first.clone
+ end
+ end
+ end
+ else
+ @servers << ARGV
+ if @i2_options.size > 1 # We added stuff in with cmdline options
+ @i2_options << @i2_options.first.clone
+ if @ssh_environment.empty?
+ @ssh_environment << {}
+ else
+ @ssh_environment << @ssh_environment.first.clone
+ end
+ end
+ end
end
-@i2_options.merge!(opts_from_cmdline)
-if @i2_options[:login] then
- @servers = @servers.map{|h| "#{@i2_options[:login]}@#{h.gsub(/.+@/,'')}"}
+# Drop default options
+if @i2_options.size > @servers.size
+ @i2_options.shift
end
+
+if @ssh_environment.size > @servers.size
+ @ssh_environment.shift
+end
+
+
+@i2_options.each do |opt|
+ opt.merge!(opts_from_cmdline)
+end
+
+@i2_options.each_with_index do |opt, i|
+ if opt[:login]
+ @servers[i] = @servers[i].map{|h| "#{opt[:login]}@#{h.gsub(/.+@/,'')}"}
+ end
+end
+
if @servers.empty?
puts "ERROR: no servers given"
puts optparse.help
exit