Module: ShellHelpers::Sh
Constant Summary
Constants included from CLILogging
Instance Attribute Summary collapse
Instance Method Summary collapse
-
#change_sh_logger(logger) ⇒ Object
Override the default logger (which is the one provided by CLILogging).
-
#sh(*command, argv0: nil, **opts) ⇒ Object
callbacks: on_success, on_error yield process_status.success?,stdout,stderr,process_status if block_given? returns success; except in capture mode where it returns success, stdout, stderr, process_status.
-
#sh!(*args, failure_msg: nil, **opts, &block) ⇒ Object
Run a command, throwing an exception if the command exited nonzero.
-
#sh_commands(com, **opts) ⇒ Object
split commands on newlines and run sh on each line.
-
#sh_or_proc(cmd, *args, **opts, &b) ⇒ Object
returns only the success or failure.
-
#shrun(*args, mode: :system, block: nil, **opts) ⇒ Object
callback called by sh to select the exec mode mode: :system,:spawn,:exec,:capture opts: sudo, env.
- #wait_spawned ⇒ Object
Methods included from CLILogging
#change_logger, #log_and_do, #logger, setup_toggle_trap
Instance Attribute Details
#default_sh_options ⇒ Object
152 153 154 155 156 157 158 159 |
# File 'lib/shell_helpers/sh.rb', line 152 def @default_sh_options||={log: true, capture: false, on_success: nil, on_error: nil, expected:0, dryrun: false, escape: false, log_level_execute_debug: :debug, log_level_execute: :info, log_level_error: :error, log_level_stderr: :error, log_level_stdout_success: :info, log_level_stdout_fail: :warn, detach: false, mode: :system} end |
#spawned ⇒ Object
162 163 164 |
# File 'lib/shell_helpers/sh.rb', line 162 def spawned @spawned||=[] end |
Instance Method Details
#change_sh_logger(logger) ⇒ Object
Override the default logger (which is the one provided by CLILogging). You would do this if you want a custom logger or you aren't mixing-in CLILogging.
Note that this method is not called sh_logger= to avoid annoying situations where Ruby thinks you are setting a local variable
322 323 324 |
# File 'lib/shell_helpers/sh.rb', line 322 def change_sh_logger(logger) @sh_logger = logger end |
#sh(*command, argv0: nil, **opts) ⇒ Object
callbacks: on_success, on_error yield process_status.success?,stdout,stderr,process_status if block_given? returns success; except in capture mode where it returns success, stdout, stderr, process_status
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/shell_helpers/sh.rb', line 229 def sh(*command, argv0: nil, **opts) defaults= curopts=defaults.dup defaults.keys.each do |k| v=opts.delete(k) curopts[k]=v unless v.nil? end log=curopts[:log] command=[[command.first, argv0], *command[1..-1]] if argv0 and command.length > 1 and !curopts[:escape] if command.length==1 and command.first.kind_of?(Array) #so that sh(["ls", "-a"]) works command=command.first command=[[command.first, argv0], *command[1..-1]] if argv0 and !curopts[:escape] end command_name = curopts[:name] || command_name(command) #this keep the options # this should not be needed command=command.shelljoin if curopts[:escape] if log sh_logger.send(curopts[:log_level_execute], SimpleColor.color("Executing '#{command_name}'",:bold)) p_env, p_args, p_opts= Run.process_command(*command, **opts) sh_logger.send(curopts[:log_level_execute_debug], SimpleColor.color("Debug execute: #{[p_env, *p_args, p_opts]}", :bold)) end if !curopts[:dryrun] if curopts[:capture] || curopts[:mode]==:capture stdout,stderr,status = shrun(*command,**opts,mode: :capture) elsif curopts[:detach] || curopts[:mode]==:spawn || curopts[:mode]==:detach mode = curopts[:detach] ? :detach : curops[:mode] _pid = shrun(*command,**opts, mode: mode) status=0; stdout=nil; stderr=nil elsif curopts[:mode]==:run status, stdout, stderr=shrun(*command,mode: curopts[:mode], **opts) else mode = curopts[:mode] || :system shrun(*command,mode: mode, **opts) status=$?; stdout=nil; stderr=nil end else sh_logger.info command.to_s status=0; stdout=nil; stderr=nil end process_status = ProcessStatus.new(status,curopts[:expected]) sh_logger.send(curopts[:log_level_stderr], SimpleColor.color("stderr output of '#{command_name}':\n",:bold,:red)+stderr) unless stderr.nil? or stderr.strip.length == 0 or !log if process_status.success? sh_logger.send(curopts[:log_level_stdout_success], SimpleColor.color("stdout output of '#{command_name}':\n",:bold,:green)+stdout) unless stdout.nil? or stdout.strip.length == 0 or !log curopts[:on_success].call(stdout,stderr,process_status) unless curopts[:on_success].nil? # block.call(stdout,stderr,process_status) unless block.nil? else sh_logger.send(curopts[:log_level_stdout_fail], SimpleColor.color("stdout output of '#{command_name}':\n",:bold,:yellow)+stdout) unless stdout.nil? or stdout.strip.length == 0 or !log sh_logger.send(curopts[:log_level_error], SimpleColor.color("Error running '#{command_name}': #{process_status.status}",:red,:bold)) if log curopts[:on_error].call(stdout,stderr,process_status) unless curopts[:on_error].nil? end yield process_status.success?,stdout,stderr,process_status if block_given? if curopts[:capture] || curopts[:mode]==:capture || curopts[:mode]==:run return process_status.success?,stdout,stderr,process_status else return process_status.success? end rescue SystemCallError => ex sh_logger.send(curopts[:log_level_error], SimpleColor.color("Error running '#{command_name}': #{ex.}",:red,:bold)) if log if block_given? yield 127, nil, nil, nil else return 127, nil, nil, nil end end |
#sh!(*args, failure_msg: nil, **opts, &block) ⇒ Object
Run a command, throwing an exception if the command exited nonzero. Otherwise, behaves exactly like #sh. Raises SH::FailedCommandError if the command exited nonzero. Examples:
sh!("rsync foo bar")
# => if command fails, app exits and user sees: "error: Command 'rsync foo bar' exited 12"
sh!("rsync foo bar", :failure_msg => "Couldn't rsync, check log for details")
# => if command fails, app exits and user sees: "error: Couldn't rsync, check log for details
308 309 310 311 312 313 314 |
# File 'lib/shell_helpers/sh.rb', line 308 def sh!(*args,failure_msg: nil,**opts, &block) on_error=Proc.new do |*blockargs| process_status=blockargs.last raise FailedCommandError.new(process_status.exitstatus,command_name(args),failure_msg: failure_msg) end sh(*args,**opts,on_error: on_error,&block) end |
#sh_commands(com, **opts) ⇒ Object
split commands on newlines and run sh on each line
327 328 329 330 331 |
# File 'lib/shell_helpers/sh.rb', line 327 def sh_commands(com, **opts) com.each_line do |line| sh(line.chomp,**opts) end end |
#sh_or_proc(cmd, *args, **opts, &b) ⇒ Object
returns only the success or failure
334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/shell_helpers/sh.rb', line 334 def sh_or_proc(cmd, *args, **opts, &b) case cmd when Proc cmd.call(*args, **opts, &b) when Array suc, _r=SH.sh(*cmd, *args, **opts, &b) suc when String suc, _r=SH.sh(cmd + " #{args.shelljoin}", **opts, &b) suc end end |
#shrun(*args, mode: :system, block: nil, **opts) ⇒ Object
callback called by sh to select the exec mode mode: :system,:spawn,:exec,:capture opts: sudo, env
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/shell_helpers/sh.rb', line 172 def shrun(*args,mode: :system, block: nil, **opts) env, args, spawn_opts=Run.process_command(*args, **opts) # p env, args, spawn_opts case mode when :system system(env,*args,spawn_opts) when :spawn, :detach pid=spawn(env,*args,spawn_opts, &block) if mode==:detach Process.detach(pid) else spawned << pid if block_given? yield pid Process.wait(pid) else pid end end when :exec exec(env,*args,spawn_opts, &block) when :capture Run.run_command(env,*args,spawn_opts, &block) when :run Run.run(env,*args,spawn_opts, &block) else raise ShError.new("In shrun, mode #{mode} not understood") end end |
#wait_spawned ⇒ Object
165 166 167 |
# File 'lib/shell_helpers/sh.rb', line 165 def wait_spawned spawned.each {|c| Process.waitpid(c)} end |