Top Level Namespace
Defined Under Namespace
Modules: Exeggutor
Instance Method Summary collapse
-
#exeg(args, can_fail: false, show_stdout: false, show_stderr: false, env: nil, chdir: nil, stdin_data: nil) ⇒ ProcessResult
Executes a command with the provided arguments and options.
-
#exeg_async(args, env: nil, chdir: nil) ⇒ ProcessHandle
Executes a command with the provided arguments and options.
Instance Method Details
#exeg(args, can_fail: false, show_stdout: false, show_stderr: false, env: nil, chdir: nil, stdin_data: nil) ⇒ ProcessResult
Executes a command with the provided arguments and options. Waits for the process to finish.
163 164 165 166 167 168 169 170 171 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 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/exeggutor.rb', line 163 def exeg(args, can_fail: false, show_stdout: false, show_stderr: false, env: nil, chdir: nil, stdin_data: nil) raise "args.size must be >= 1" if args.empty? stdin_io, stdout_io, stderr_io, wait_thr = Exeggutor::run_popen3(args, env, chdir) stdin_io.write(stdin_data) if stdin_data stdin_io.close # Make the streams as synchronous as possible, to minimize the possibility of a surprising lack # of output stdout_io.sync = true stderr_io.sync = true stdout = +'' stderr = +'' # Although there could be more code sharing between this and exeg_async, it would either complicate exeg_async's inner workings # or force us to pay the same performance cost that exeg_async does remaining_ios = [stdout_io, stderr_io] while remaining_ios.size > 0 readable_ios, = IO.select(remaining_ios) for readable_io in readable_ios begin data = readable_io.read_nonblock(100_000) if readable_io == stdout_io stdout << data $stdout.print(data) if show_stdout else stderr << data $stderr.print(data) if show_stderr end rescue IO::WaitReadable # Shouldn't usually happen because IO.select indicated data is ready, but maybe due to EINTR or something next rescue EOFError remaining_ios.delete(readable_io) end end end result = Exeggutor::ProcessResult.new( stdout: stdout, stderr: stderr, exit_code: wait_thr.value.exitstatus, pid: wait_thr.pid ) if !can_fail && !result.success? error_str = <<~ERROR_STR Command failed: #{args.shelljoin} Exit code: #{result.exit_code} stdout: #{result.stdout} stderr: #{result.stderr} pid: #{result.pid} ERROR_STR raise Exeggutor::ProcessError.new(result), error_str end result end |
#exeg_async(args, env: nil, chdir: nil) ⇒ ProcessHandle
Executes a command with the provided arguments and options. Does not wait for the process to finish.
230 231 232 |
# File 'lib/exeggutor.rb', line 230 def exeg_async(args, env: nil, chdir: nil) Exeggutor::ProcessHandle.new(args, env: env, chdir: chdir) end |