sesh 0.0.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.
- checksums.yaml +7 -0
- data/bin/sesh +192 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 471da2a6d1c23302beb0858f3bcaf8dde2ea0730
|
4
|
+
data.tar.gz: 0c84359f0c8f57327e59cd7a81d4ad86187f56c4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 478ed2e28e910409295fc525752f3d1f1a76c88d8e78b2d66874eb1195c226a6beff0b334db0be9e0abbffaa4e6ff03c4e2a7b912062f0fecbc5250305b03812
|
7
|
+
data.tar.gz: b308849d0a53fdf43fa86cc1e97c278c497cece0e2958b32ac8eefe562550c3a17587cbfe069bb1e6c14f06ca065348ed62de5c93881dc48a2876459057b5441
|
data/bin/sesh
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if ARGV.include? '-h' or ARGV.include? '--help' then puts <<-HELP
|
4
|
+
Sesh: remote background sessions powered by tmux and tmuxinator.
|
5
|
+
Runs a headless tmuxinator session for remote slave machines to connect to.
|
6
|
+
|
7
|
+
Usage: #{File.basename $0} [command] [project]
|
8
|
+
|
9
|
+
Commands:
|
10
|
+
|
11
|
+
sesh new Create a new tmuxinator configuration.
|
12
|
+
sesh start [project_name] Start a Sesh session for a project.
|
13
|
+
sesh stop [project_name] Stop a Sesh session for a project.
|
14
|
+
sesh list List running Sesh sessions on this machine.
|
15
|
+
sesh connect [project] user@host Connect as a slave to a remote Sesh session.
|
16
|
+
sesh enslave [project] user@host Connect a slave to a local Sesh session.
|
17
|
+
|
18
|
+
HELP
|
19
|
+
exit; end
|
20
|
+
|
21
|
+
def warn(msg) $stderr.puts msg end
|
22
|
+
def fatal(msg) $stderr.puts msg; $stderr.puts; exit 1 end
|
23
|
+
def debug(msg) $stderr.puts "> #{msg}" end
|
24
|
+
|
25
|
+
@command = ARGV[0]
|
26
|
+
@options = ARGV[1..-1] || []
|
27
|
+
# debug("Options received: #{@options}") if @options.any?
|
28
|
+
|
29
|
+
def get_project_name
|
30
|
+
if @options.any?
|
31
|
+
pn_opt = if %w(connect enslave).include? @command
|
32
|
+
@options.shift if @options[1]
|
33
|
+
else
|
34
|
+
@options[0]
|
35
|
+
end
|
36
|
+
if pn_opt
|
37
|
+
pn_opt_path = File.expand_path("~/.tmuxinator/#{pn_opt}.yml")
|
38
|
+
return pn_opt if File.exist? pn_opt_path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
`printf '%q\n' "${PWD##*/}"`.strip
|
42
|
+
end
|
43
|
+
@project_name = get_project_name
|
44
|
+
|
45
|
+
def get_local_username
|
46
|
+
`echo $USER`.strip
|
47
|
+
end
|
48
|
+
def get_local_hostname
|
49
|
+
`scutil --get LocalHostName`.strip.downcase + '.local'
|
50
|
+
end
|
51
|
+
@local_ssh_addr = "#{get_local_username}@#{get_local_hostname}"
|
52
|
+
|
53
|
+
@socket = "/tmp/#{@project_name}.sock"
|
54
|
+
|
55
|
+
def project_name_matcher
|
56
|
+
pn = @project_name.gsub '-', '\-'
|
57
|
+
"[t]mux.*[#{pn[0]}]#{pn[1..-1]}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def already_running?
|
61
|
+
output = `ps aux | grep "#{project_name_matcher}"`.strip
|
62
|
+
output.length > 0
|
63
|
+
end
|
64
|
+
|
65
|
+
def format_command(command) command.gsub(/\ [ ]+/, ' ').strip end
|
66
|
+
def format_and_run_command(command) `#{format_command(command)}`.strip end
|
67
|
+
|
68
|
+
def issue_server_start_command!
|
69
|
+
`tmux -vvvv -S "#{@socket}" new-session -d "env TMUX='' mux start #{@project_name}"`
|
70
|
+
end
|
71
|
+
|
72
|
+
def issue_server_stop_command!
|
73
|
+
`pkill -f "#{project_name_matcher}"`
|
74
|
+
end
|
75
|
+
|
76
|
+
def connection_command(local=false)
|
77
|
+
local_command = "tmux -S #{@socket} a"
|
78
|
+
return local_command if local
|
79
|
+
"ssh #{@local_ssh_addr} -t '#{local_command}'"
|
80
|
+
end
|
81
|
+
|
82
|
+
def enter_slave_mode_command(local=false)
|
83
|
+
tell_iterm_app = 'tell application "iTerm"'
|
84
|
+
tell_iterm_process = 'tell application "System Events" to tell process "iTerm"'
|
85
|
+
format_command <<-BASH
|
86
|
+
osascript \
|
87
|
+
-e '#{tell_iterm_app} to activate' \
|
88
|
+
-e '#{tell_iterm_process} to keystroke \"n\" using command down' \
|
89
|
+
-e 'delay 1' \
|
90
|
+
-e '#{tell_iterm_app} to tell session -1 of current terminal to \
|
91
|
+
write text "#{connection_command(local).gsub("'", '\\\\\'')}"' \
|
92
|
+
-e '#{tell_iterm_process} to keystroke return using command down'
|
93
|
+
BASH
|
94
|
+
end
|
95
|
+
|
96
|
+
def show_progress_until(condition_lambda, timeout=10)
|
97
|
+
started_progress_at = Time.now
|
98
|
+
return true if condition_lambda.call
|
99
|
+
print '> '
|
100
|
+
until condition_lambda.call or Time.now - started_progress_at > timeout
|
101
|
+
print '.'
|
102
|
+
$stdout.flush
|
103
|
+
sleep 0.5
|
104
|
+
end
|
105
|
+
puts
|
106
|
+
return condition_lambda.call
|
107
|
+
end
|
108
|
+
|
109
|
+
if @command
|
110
|
+
case @command
|
111
|
+
when 'start'
|
112
|
+
fatal("Sesh project '#{@project_name}' is already running!") if already_running?
|
113
|
+
debug "Starting Sesh project '#{@project_name}'..."
|
114
|
+
output = issue_server_start_command!
|
115
|
+
success = show_progress_until ->{ already_running? }
|
116
|
+
if success
|
117
|
+
sleep 1
|
118
|
+
if $? && already_running?
|
119
|
+
debug 'Sesh started successfully.'
|
120
|
+
debug "To connect: #{connection_command}"
|
121
|
+
puts
|
122
|
+
else
|
123
|
+
fatal 'Sesh failed to start!'
|
124
|
+
end
|
125
|
+
else
|
126
|
+
fatal 'Sesh failed to start after ten seconds!'
|
127
|
+
end
|
128
|
+
when 'stop'
|
129
|
+
fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
|
130
|
+
debug "Stopping Sesh project '#{@project_name}'..."
|
131
|
+
output = issue_server_stop_command!
|
132
|
+
success = show_progress_until ->{ !already_running? }
|
133
|
+
if success && $?
|
134
|
+
debug 'Sesh stopped successfully.'
|
135
|
+
puts
|
136
|
+
else
|
137
|
+
fatal 'Sesh failed to stop after ten seconds!'
|
138
|
+
end
|
139
|
+
when 'restart'
|
140
|
+
fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
|
141
|
+
puts `sesh stop #{@project_name} #{@options if @options.any?}`.strip
|
142
|
+
sleep(0.5)
|
143
|
+
puts `sesh start #{@project_name} #{@options if @options.any?}`.strip
|
144
|
+
when 'new'
|
145
|
+
command = "env EDITOR='vim' tmuxinator new #{@project_name}"
|
146
|
+
output = exec command
|
147
|
+
puts
|
148
|
+
when 'list'
|
149
|
+
output = format_and_run_command <<-BASH
|
150
|
+
ps aux | grep tmux | grep "env TMUX='' mux start" \
|
151
|
+
| grep -v "[g]rep" | sed -e "s/.*mux start \\(.*\\)/\\1/"
|
152
|
+
BASH
|
153
|
+
running_projects = output.split("\n")
|
154
|
+
pcount = running_projects.count
|
155
|
+
if pcount > 0
|
156
|
+
puts "#{pcount} project#{pcount>1 ? 's':''} currently running:"
|
157
|
+
puts running_projects
|
158
|
+
puts
|
159
|
+
else
|
160
|
+
fatal "There are no Sesh projects currently running."
|
161
|
+
end
|
162
|
+
when 'connect'
|
163
|
+
slave_address = @options[0]
|
164
|
+
if (is_local=slave_address.nil?)
|
165
|
+
slave_address = @local_ssh_addr
|
166
|
+
fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
|
167
|
+
end
|
168
|
+
command = enter_slave_mode_command(is_local)
|
169
|
+
puts command
|
170
|
+
puts `#{command}`.strip
|
171
|
+
when 'enslave'
|
172
|
+
fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
|
173
|
+
fatal("You must specify a machine to enslave! Eg: user@ip") unless @options.any?
|
174
|
+
slave_address = @options[0]
|
175
|
+
debug "Attempting to connect #{slave_address} to Sesh project '#{@project_name}'..."
|
176
|
+
output = format_and_run_command <<-BASH
|
177
|
+
ssh #{slave_address} "#{enter_slave_mode_command.gsub('"', '\"')}"
|
178
|
+
BASH
|
179
|
+
puts output
|
180
|
+
if $?
|
181
|
+
debug "Sesh client connected successfully."
|
182
|
+
puts
|
183
|
+
else
|
184
|
+
fatal 'Sesh client failed to start.'
|
185
|
+
end
|
186
|
+
else
|
187
|
+
fatal "Command not recognized!"
|
188
|
+
end
|
189
|
+
exit 0
|
190
|
+
end
|
191
|
+
|
192
|
+
fatal 'You must specify a command.'
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sesh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MacKinley Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Remote background sessions powered by tmux and tmuxinator.
|
14
|
+
email: smithmackinley@gmail.com
|
15
|
+
executables:
|
16
|
+
- sesh
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/sesh
|
21
|
+
homepage: http://rubygems.org/gems/sesh
|
22
|
+
licenses:
|
23
|
+
- GNU GPLv3
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.2.2
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: Sesh
|
45
|
+
test_files: []
|
46
|
+
has_rdoc:
|