Class: Sunshine::Shell
Overview
The Shell class handles local input, output and execution to the shell.
Direct Known Subclasses
Defined Under Namespace
Classes: TimeoutError
Constant Summary collapse
- TIMEOUT =
Time to wait with no activity until giving up on a command.
120
- LOCAL_USER =
`whoami`.chomp
- LOCAL_HOST =
`hostname`.chomp
- SUDO_FAILED =
/^Sorry, try again./
- SUDO_PROMPT =
/^Password:/
Instance Attribute Summary collapse
-
#env ⇒ Object
Returns the value of attribute env.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#input ⇒ Object
readonly
Returns the value of attribute input.
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
-
#output ⇒ Object
readonly
Returns the value of attribute output.
-
#password ⇒ Object
readonly
Returns the value of attribute password.
-
#sudo ⇒ Object
Returns the value of attribute sudo.
-
#user ⇒ Object
readonly
Returns the value of attribute user.
Instance Method Summary collapse
-
#==(shell) ⇒ Object
Checks for equality.
-
#agree(*args, &block) ⇒ Object
Prompt the user to agree.
-
#ask(*args, &block) ⇒ Object
Prompt the user for input.
-
#call(cmd, options = {}, &block) ⇒ Object
Execute a command on the local system and return the output.
-
#close ⇒ Object
Close the output IO.
-
#connect ⇒ Object
Returns true.
-
#connected? ⇒ Boolean
Returns true.
-
#disconnect ⇒ Object
Returns true.
-
#download(from_path, to_path, options = {}, &block) ⇒ Object
(also: #upload)
Copies a file.
-
#env_cmd(cmd, env_hash = @env) ⇒ Object
Build an env command if an env_hash is passed.
-
#execute(cmd) ⇒ Object
Execute a command with open4 and loop until the process exits.
-
#expand_path(path) ⇒ Object
Expands the path.
-
#file?(filepath) ⇒ Boolean
Checks if file exists.
-
#initialize(output = $stdout, options = {}) ⇒ Shell
constructor
A new instance of Shell.
-
#make_file(filepath, content, options = {}) ⇒ Object
Write a file.
-
#os_name ⇒ Object
Get the name of the OS.
-
#prompt_for_password ⇒ Object
Prompt the user for a password.
-
#sh_cmd(string) ⇒ Object
Build an sh -c command.
-
#sudo_cmd(cmd, sudo_val = nil) ⇒ Object
Build a command with sudo.
-
#symlink(target, symlink_name) ⇒ Object
Force symlinking a directory.
-
#sync ⇒ Object
Synchronize a block with the current mutex if it exists.
-
#timed_out?(start_time = @cmd_activity, max_time = TIMEOUT) ⇒ Boolean
Checks if timeout occurred.
-
#update_timeout ⇒ Object
Update the time of the last command activity.
-
#with_mutex(mutex) ⇒ Object
Execute a block while setting the shell’s mutex.
-
#write(str) ⇒ Object
(also: #<<)
Write string to stdout (by default).
Constructor Details
#initialize(output = $stdout, options = {}) ⇒ Shell
Returns a new instance of Shell.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/sunshine/shell.rb', line 25 def initialize output = $stdout, ={} @output = output $stdin.sync @input = HighLine.new $stdin @user = LOCAL_USER @host = LOCAL_HOST @sudo = [:sudo] @env = [:env] || {} @password = [:password] @cmd_activity = nil @mutex = nil end |
Instance Attribute Details
#env ⇒ Object
Returns the value of attribute env.
23 24 25 |
# File 'lib/sunshine/shell.rb', line 23 def env @env end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
22 23 24 |
# File 'lib/sunshine/shell.rb', line 22 def host @host end |
#input ⇒ Object (readonly)
Returns the value of attribute input.
22 23 24 |
# File 'lib/sunshine/shell.rb', line 22 def input @input end |
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
22 23 24 |
# File 'lib/sunshine/shell.rb', line 22 def mutex @mutex end |
#output ⇒ Object (readonly)
Returns the value of attribute output.
22 23 24 |
# File 'lib/sunshine/shell.rb', line 22 def output @output end |
#password ⇒ Object (readonly)
Returns the value of attribute password.
22 23 24 |
# File 'lib/sunshine/shell.rb', line 22 def password @password end |
#sudo ⇒ Object
Returns the value of attribute sudo.
23 24 25 |
# File 'lib/sunshine/shell.rb', line 23 def sudo @sudo end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
22 23 24 |
# File 'lib/sunshine/shell.rb', line 22 def user @user end |
Instance Method Details
#==(shell) ⇒ Object
Checks for equality
47 48 49 |
# File 'lib/sunshine/shell.rb', line 47 def == shell @host == shell.host && @user == shell.user rescue false end |
#agree(*args, &block) ⇒ Object
Prompt the user to agree.
63 64 65 |
# File 'lib/sunshine/shell.rb', line 63 def agree(*args, &block) sync{ @input.agree(*args, &block) } end |
#ask(*args, &block) ⇒ Object
Prompt the user for input.
55 56 57 |
# File 'lib/sunshine/shell.rb', line 55 def ask(*args, &block) sync{ @input.ask(*args, &block) } end |
#call(cmd, options = {}, &block) ⇒ Object
Execute a command on the local system and return the output.
71 72 73 |
# File 'lib/sunshine/shell.rb', line 71 def call cmd, ={}, &block execute sudo_cmd(cmd, ), &block end |
#close ⇒ Object
Close the output IO. (Required by the Logger class)
79 80 81 |
# File 'lib/sunshine/shell.rb', line 79 def close @output.close end |
#connect ⇒ Object
Returns true. Compatibility method with RemoteShell.
87 88 89 |
# File 'lib/sunshine/shell.rb', line 87 def connect true end |
#connected? ⇒ Boolean
Returns true. Compatibility method with RemoteShell.
95 96 97 |
# File 'lib/sunshine/shell.rb', line 95 def connected? true end |
#disconnect ⇒ Object
Returns true. Compatibility method with RemoteShell.
103 104 105 |
# File 'lib/sunshine/shell.rb', line 103 def disconnect true end |
#download(from_path, to_path, options = {}, &block) ⇒ Object Also known as: upload
Copies a file. Compatibility method with RemoteShell.
111 112 113 114 115 |
# File 'lib/sunshine/shell.rb', line 111 def download from_path, to_path, ={}, &block Sunshine.logger.info @host, "Copying #{from_path} -> #{to_path}" do FileUtils.cp_r from_path, to_path end end |
#env_cmd(cmd, env_hash = @env) ⇒ Object
Build an env command if an env_hash is passed
165 166 167 168 169 170 171 |
# File 'lib/sunshine/shell.rb', line 165 def env_cmd cmd, env_hash=@env if env_hash && !env_hash.empty? env_vars = env_hash.map{|e| e.join("=")} cmd = ["env", env_vars, cmd] end cmd end |
#execute(cmd) ⇒ Object
Execute a command with open4 and loop until the process exits. The cmd argument may be a string or an array. If a block is passed, it will be called when data is received and passed the stream type and stream string value:
shell.execute "test -s 'blah' && echo 'true'" do |stream, str|
stream #=> :stdout
string #=> 'true'
end
The method returns the output from the stdout stream by default, and raises a CmdError if the exit status of the command is not zero.
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/sunshine/shell.rb', line 280 def execute cmd cmd = [cmd] unless Array === cmd pid, inn, out, err = popen4(*cmd) inn.sync = true log_methods = {out => :debug, err => :error} result, status = process_streams(pid, out, err) do |stream, data| stream_name = stream == out ? :out : :err # User blocks should run with sync threads to avoid badness. sync do Sunshine.logger.send log_methods[stream], "#{@host}:#{stream_name}", data yield(stream_name, data, inn) if block_given? end if password_required?(stream_name, data) then kill_process(pid) unless Sunshine.interactive? send_password_to_stream(inn, data) end end raise_command_failed(status, cmd) unless status.success? result[out].join.chomp ensure inn.close rescue nil out.close rescue nil err.close rescue nil end |
#expand_path(path) ⇒ Object
Expands the path. Compatibility method with RemoteShell.
123 124 125 |
# File 'lib/sunshine/shell.rb', line 123 def path File. path end |
#file?(filepath) ⇒ Boolean
Checks if file exists. Compatibility method with RemoteShell.
131 132 133 |
# File 'lib/sunshine/shell.rb', line 131 def file? filepath File.file? filepath end |
#make_file(filepath, content, options = {}) ⇒ Object
Write a file. Compatibility method with RemoteShell.
139 140 141 |
# File 'lib/sunshine/shell.rb', line 139 def make_file filepath, content, ={} File.open(filepath, "w+"){|f| f.write(content)} end |
#os_name ⇒ Object
Get the name of the OS
147 148 149 |
# File 'lib/sunshine/shell.rb', line 147 def os_name @os_name ||= call("uname -s").strip.downcase end |
#prompt_for_password ⇒ Object
Prompt the user for a password
155 156 157 158 159 |
# File 'lib/sunshine/shell.rb', line 155 def prompt_for_password @password = ask("#{@user}@#{@host} Password:") do |q| q.echo = false end end |
#sh_cmd(string) ⇒ Object
Build an sh -c command
177 178 179 180 181 |
# File 'lib/sunshine/shell.rb', line 177 def sh_cmd string string = string.gsub(/'/){|s| "'\\''"} ["sh", "-c", "'#{string}'"] end |
#sudo_cmd(cmd, sudo_val = nil) ⇒ Object
Build a command with sudo. If sudo_val is nil, it is considered to mean “pass-through” and the default shell sudo will be used. If sudo_val is false, the cmd will be returned unchanged. If sudo_val is true, the returned command will be prefaced with sudo -H If sudo_val is a String, the command will be prefaced with sudo -H -u string_value
194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/sunshine/shell.rb', line 194 def sudo_cmd cmd, sudo_val=nil sudo_val = sudo_val[:sudo] if Hash === sudo_val sudo_val = @sudo if sudo_val.nil? case sudo_val when true ["sudo", "-H", cmd].flatten when String ["sudo", "-H", "-u", sudo_val, cmd].flatten else cmd end end |
#symlink(target, symlink_name) ⇒ Object
Force symlinking a directory.
212 213 214 |
# File 'lib/sunshine/shell.rb', line 212 def symlink target, symlink_name call "ln -sfT #{target} #{symlink_name}" rescue false end |
#sync ⇒ Object
Synchronize a block with the current mutex if it exists.
220 221 222 223 224 225 226 |
# File 'lib/sunshine/shell.rb', line 220 def sync if @mutex @mutex.synchronize{ yield } else yield end end |
#timed_out?(start_time = @cmd_activity, max_time = TIMEOUT) ⇒ Boolean
Checks if timeout occurred.
232 233 234 |
# File 'lib/sunshine/shell.rb', line 232 def timed_out? start_time=@cmd_activity, max_time=TIMEOUT Time.now.to_i - start_time.to_i > max_time end |
#update_timeout ⇒ Object
Update the time of the last command activity
240 241 242 |
# File 'lib/sunshine/shell.rb', line 240 def update_timeout @cmd_activity = Time.now end |
#with_mutex(mutex) ⇒ Object
Execute a block while setting the shell’s mutex. Sets the mutex to its original value on exit. Executing commands with a mutex is used for user prompts.
250 251 252 253 254 |
# File 'lib/sunshine/shell.rb', line 250 def with_mutex mutex old_mutex, @mutex = @mutex, mutex yield @mutex = old_mutex end |
#write(str) ⇒ Object Also known as: <<
Write string to stdout (by default).
260 261 262 |
# File 'lib/sunshine/shell.rb', line 260 def write str @output.write str end |