tmux-cssh 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e98cc319a8b74ce0ef895d7ca295621028ae6e6
4
+ data.tar.gz: 0dab99e91d4471541ecaa78269acf97ad8d26525
5
+ SHA512:
6
+ metadata.gz: 70ec48338850dc68cad71debe431be1cfd0ae530f1d57ab10d9cba7d91a5cf21c40b5c64f617c250795f8b37f3369cd7da73c518220b7c3dd3504c9abca3f506
7
+ data.tar.gz: 03e40a19d8af851efc3bac78a26b05219abf2f2a770a9546a9d263574a70031a9d05741a2c64d154595ba633cdf855adbca35a9c7ad02f95c46fb7ff8c85c883
@@ -0,0 +1,15 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ _yardoc
8
+ coverage
9
+ lib/bundler/man
10
+ pkg
11
+ rdoc
12
+ spec/reports
13
+ test/tmp
14
+ test/version_tmp
15
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
File without changes
@@ -0,0 +1,80 @@
1
+ # tmux-cssh-rb
2
+
3
+ ## Requirements
4
+
5
+ * Ruby 1.9.3 or later
6
+ * tmux
7
+
8
+ ## Installing
9
+
10
+ ### Install from RubyGems repository
11
+
12
+ coming soon...
13
+
14
+ ### Build gem and install
15
+
16
+ ```sh
17
+ git clone https://github.com/yshh/tmux-cssh-rb.git path/to/tmux-cssh-rb
18
+ cd path/to/tmux-cssh-rb
19
+ gem build tmux-cssh.gemspec
20
+ gem install tmux-cssh-*.gem
21
+ ```
22
+
23
+ ### Use Bundler
24
+
25
+ Write the line below to your Gemfile:
26
+ ```ruby
27
+ gem 'tmux-cssh', git: 'https://github.com/yshh/tmux-cssh-rb.git'
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```
33
+ % tssh -h
34
+ Usage: tssh [options]
35
+ -l, --login USERNAME
36
+ -c, --config FILE
37
+ --ssh SSH_COMMAND
38
+ --ssh_args SSH_ARGUMENTS
39
+ --debug DEBUG_LEVEL
40
+ --panes_per_window NUM
41
+ ```
42
+
43
+ `tssh` should be executed outside of tmux session.
44
+
45
+ ```sh
46
+ tssh user@host1 host2 host3
47
+ ```
48
+
49
+ ### Sync mode
50
+
51
+ When you type to pane, key strokes are copied to all panes in the window.
52
+ Use tmux command `set-window-option synchronize-panes` to disable this mode.
53
+
54
+ You may want to bind a shortcut key to this command (add the line below to your ~/.tmux.conf)
55
+
56
+ ```
57
+ bind-key g setw synchronize-panes
58
+ ```
59
+
60
+ ### How to exit
61
+
62
+ Panes do not close after the ssh session terminates
63
+ (using `set remain-on-exit`) so that you can see error messages in the case
64
+ ssh session terminated unexpectedly by errors such as connection error and
65
+ authentication failure.
66
+
67
+ You can close dead panes with tmux commands:
68
+
69
+ * `kill-pane` (closes selected pane; bound to `C-b x` by default) or
70
+ * `kill-window` (closes all panes in current window; bound to `C-b &` by default)
71
+
72
+ ## OS limits
73
+
74
+ Opening many tmux panes hits some OS limits.
75
+
76
+ * num of pty
77
+ * max open files
78
+
79
+ ## Known issues
80
+
@@ -0,0 +1,99 @@
1
+ # tmux-cssh-rb
2
+
3
+ ## 必要環境
4
+
5
+ * Ruby 1.9.3 以上
6
+ * tmux
7
+
8
+ ## インストール
9
+
10
+ ### gem コマンド
11
+
12
+ TODO: RubyGems リポジトリに上げる
13
+
14
+ GitHub リポジトリから直接インストールする場合は以下を実行してください。
15
+
16
+ ```sh
17
+ gem install specific_install
18
+ gem specific_install https://github.com/yshh/tmux-cssh-rb.git
19
+ ```
20
+
21
+ ### ビルド・インストール
22
+
23
+ ```sh
24
+ git clone https://github.com/yshh/tmux-cssh-rb.git path/to/tmux-cssh-rb
25
+ cd path/to/tmux-cssh-rb
26
+ gem build tmux-cssh.gemspec
27
+ gem install tmux-cssh-*.gem
28
+ ```
29
+
30
+ ### Bundler を使う
31
+
32
+ Gemfile に以下を1行追加してください。
33
+
34
+ ```ruby
35
+ gem 'tmux-cssh', git: 'https://github.com/yshh/tmux-cssh-rb.git'
36
+ ```
37
+
38
+ ## 使い方
39
+
40
+ `tssh` は tmux セッションの外で実行する必要があります。
41
+ tmux セッション内での実行は現状サポート(?)外です。
42
+
43
+ ```sh
44
+ tssh user@host1 host2 host3
45
+ ```
46
+
47
+ `-h` オプションをつけて実行するとヘルプが表示されます。
48
+
49
+ ```
50
+ % tssh -h
51
+ Usage: tssh [options]
52
+ -l, --login USERNAME
53
+ -c, --config FILE
54
+ --ssh SSH_COMMAND
55
+ --ssh_args SSH_ARGUMENTS
56
+ --debug DEBUG_LEVEL
57
+ --panes_per_window NUM
58
+ ```
59
+
60
+ ### Sync モード
61
+
62
+ ひとつの pane にタイプした文字は、window 内の全ての pane にコピーされます。
63
+ これは tmux の機能を使っており、
64
+ tmux コマンド `set-window-option synchronize-panes` で無効化できます。
65
+ この tmux コマンドにショートカットキーを割り当てると便利です。
66
+
67
+ 例えば以下の tmux コマンドを ~/.tmux.conf に追加する:
68
+
69
+ ```
70
+ bind-key g setw synchronize-panes
71
+ ```
72
+
73
+ 詳細については tmux のマニュアルを参照してください。
74
+
75
+ ### 終了方法
76
+
77
+ pane は ssh セッションの終了後に自動的には終了しません
78
+ (tmux の `set-window-option remain-on-exit` を設定しています)。
79
+ 認証えらーなどでセッションが意図せずエラー終了した際、エラーメッセージが
80
+ 消えてしまうのを防ぐためです。
81
+
82
+ pane は以下の tmux コマンドで閉じることができます。
83
+
84
+ * `kill-pane` (選択中の pane を閉じる; デフォルト: `C-b x`)
85
+ * `kill-window` (window 上の全ての pane を閉じる; デフォルト: `C-b &`)
86
+
87
+ ## OS の制限
88
+
89
+ たくさんの tmux pane を開くと、OS の各種上限に当たります。
90
+
91
+ * pty 数
92
+ * max open files
93
+
94
+ TODO: 回避方法
95
+
96
+ ## 既知の問題
97
+
98
+ XXX
99
+
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'logger'
4
+ require 'inifile'
5
+ require 'optparse'
6
+ require 'tssh'
7
+
8
+ # default options
9
+ options = {
10
+ login: nil,
11
+ config: "#{ENV['HOME']}/.tsshrc",
12
+ # tile_x: nil,
13
+ # tile_y: nil,
14
+ # ssh: '/usr/local/bin/proxychains4 ssh',
15
+ ssh: 'ssh',
16
+ ssh_args: '',
17
+ # remote_command: nil,
18
+ # hosts: nil,
19
+ # session_max: 256,
20
+ # ping_test: nil,
21
+ # ping_timeout: nil,
22
+ # sock: nil,
23
+ # sorthosts: false,
24
+ # slave_settings_set: nil,
25
+ # master_settings_set: nil,
26
+ # interleave: nil,
27
+ debug: 0,
28
+
29
+ panes_per_window: 128,
30
+ }
31
+
32
+ args = {}
33
+
34
+ ARGV.options do |opt|
35
+ opt.on('-l', '--login USERNAME',
36
+ "SSH login name (default: #{options[:login]})"
37
+ ) { |v| args[:login] = v }
38
+ opt.on('-c', '--config FILE',
39
+ "Config file path (default: #{options[:config]})"
40
+ ) { |v|
41
+ raise "Config file '#{v}' does not exist" unless File.exists?(v)
42
+ args[:config] = v
43
+ }
44
+ opt.on('--ssh SSH_COMMAND',
45
+ "Custom SSH command (default: #{options[:config]})"
46
+ ) { |v| args[:ssh] = v }
47
+ opt.on('--ssh_args SSH_ARGUMENTS') do |v|
48
+ args[:ssh_args] = v
49
+ end
50
+ opt.on('--debug DEBUG_LEVEL',
51
+ "Debug level [0-2] (default: #{options[:debug]})"
52
+ ) { |v| args[:debug] = v.to_i }
53
+ opt.on("--panes_per_window NUM",
54
+ "Max panes opened on one window (default: #{options[:panes_per_window]})"
55
+ ) { |v| args[:panes_per_window] = v.to_i }
56
+ opt.parse!
57
+ end
58
+
59
+ logger = Logger.new(STDERR)
60
+
61
+ # args "debug" and "config" are specially concerned
62
+ unless args[:debug].nil?
63
+ options[:debug] = args[:debug]
64
+ end
65
+ logger.level = case options[:debug]
66
+ when 0 then Logger::WARN
67
+ when 1 then Logger::INFO
68
+ when 2 then Logger::DEBUG
69
+ else raise "Invalid debug level: '#{options[:debug]}'"
70
+ end
71
+
72
+ unless args[:config].nil?
73
+ options[:config] = args[:config]
74
+ end
75
+
76
+ if not options[:config].nil? and File.exists?(options[:config])
77
+ logger.info "Using config file: #{options[:config]}"
78
+ # config file options overwrite the default options
79
+ config = IniFile.load(options[:config])
80
+ config['global'].each do |k, v|
81
+ # XXX
82
+ if %w(panes_per_window debug).include? k
83
+ options[k.to_sym] = v.to_i
84
+ else
85
+ options[k.to_sym] = v
86
+ end
87
+ logger.debug "option from config file: #{k} => #{v}"
88
+ end
89
+ else
90
+ logger.info "Config file #{options[:config]} does not exist"
91
+ end
92
+
93
+ # command_line args are the most prioritized
94
+ args.each do |k, v|
95
+ logger.debug "option from args: #{k} => #{v}"
96
+ options[k] = v
97
+ end
98
+
99
+ # XXX
100
+ hosts = ARGV
101
+
102
+ tssh = TmuxClusterSSH.new(options, hosts, logger)
103
+ tssh.run
104
+
@@ -0,0 +1,72 @@
1
+ class TmuxClusterSSH
2
+ def initialize options, hosts, logger
3
+ @options = options
4
+ @hosts = hosts
5
+ @logger = logger
6
+ raise "No hosts specified" if @hosts.count == 0
7
+ end
8
+
9
+ def ssh_command host
10
+ if @options[:login].nil?
11
+ "#{@options[:ssh]} #{@options[:ssh_args]} #{host}"
12
+ else
13
+ "#{@options[:ssh]} #{@options[:ssh_args]} #{@options[:login]}@#{host}"
14
+ end
15
+ end
16
+
17
+ def calc_num_panes(num)
18
+ # XXX should read tmux implementation
19
+ if num > @options[:panes_per_window]
20
+ return @options[:panes_per_window] + calc_num_panes(num - @options[:panes_per_window])
21
+ end
22
+
23
+ sqrt_num = Math.sqrt(num)
24
+ panes = sqrt_num.ceil * sqrt_num.floor
25
+ panes >= num ? panes : sqrt_num.ceil ** 2
26
+ end
27
+
28
+ def run_command cmd
29
+ @logger.info cmd
30
+ res = system cmd
31
+ case res
32
+ when nil
33
+ raise "command `#{cmd}` failed"
34
+ when false
35
+ raise "command `#{cmd}` exited with status #{$?}"
36
+ end
37
+ end
38
+
39
+ def run
40
+ num_panes = calc_num_panes(@hosts.count)
41
+ session_name = "tssh-#{$$}"
42
+ (0..num_panes-1).each do |i|
43
+ host = @hosts[i]
44
+ if host.nil?
45
+ command = "'echo;echo empty'"
46
+ else
47
+ command = "'echo #{host};exec #{ssh_command(host)}'"
48
+ end
49
+ STDERR.puts command if @options[:debug] > 0
50
+ if i == 0
51
+ # create new session
52
+ run_command "tmux new -d -s #{session_name} #{command}"
53
+ run_command "tmux setw -t #{session_name} synchronize-panes on > /dev/null"
54
+ run_command "tmux setw -t #{session_name} remain-on-exit on > /dev/null"
55
+ elsif i % @options[:panes_per_window] == 0
56
+ # create new window on existing session
57
+ run_command "tmux neww -t #{session_name} #{command}"
58
+ run_command "tmux setw -t #{session_name} synchronize-panes on > /dev/null"
59
+ run_command "tmux setw -t #{session_name} remain-on-exit on > /dev/null"
60
+ else
61
+ # add pane to active window
62
+ run_command "tmux splitw -t #{session_name} #{command}"
63
+ run_command "tmux selectl -t #{session_name} tiled > /dev/null"
64
+ end
65
+ end
66
+ # XXX
67
+ run_command 'tmux select-pane -t 0'
68
+
69
+ # attach to the session
70
+ exec "tmux attach -t #{session_name}"
71
+ end
72
+ end
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'tmux-cssh'
3
+ s.version = '0.2.1'
4
+ s.licenses = ['MIT']
5
+ s.summary = 'Cluster-SSH on tmux'
6
+ s.homepage = 'https://github.com/yshh/tmux-cssh-rb'
7
+ s.authors = ['Yusuke Hagihara']
8
+ s.email = 'yusuke.hagihara@gmail.com'
9
+ s.files = `git ls-files`.split($/)
10
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
11
+ s.add_dependency 'inifile', '~> 2.0'
12
+ s.required_ruby_version = '>= 1.9.3'
13
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tmux-cssh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Yusuke Hagihara
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: inifile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ description:
28
+ email: yusuke.hagihara@gmail.com
29
+ executables:
30
+ - tssh
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - Gemfile
36
+ - LICENSE.txt
37
+ - README.md
38
+ - README_ja.md
39
+ - Rakefile
40
+ - VERSION
41
+ - bin/tssh
42
+ - lib/tssh.rb
43
+ - tmux-cssh.gemspec
44
+ homepage: https://github.com/yshh/tmux-cssh-rb
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 1.9.3
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.2.2
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Cluster-SSH on tmux
68
+ test_files: []