Skip to content

Instantly share code, notes, and snippets.

@dkandalov
Last active June 2, 2023 14:37
Show Gist options
  • Select an option

  • Save dkandalov/0af9d05339e6b29a8213 to your computer and use it in GitHub Desktop.

Select an option

Save dkandalov/0af9d05339e6b29a8213 to your computer and use it in GitHub Desktop.
Ruby method to execute and continuously print output of long-running shell command
#!/usr/bin/ruby
require "open4"
def shell_exec(command)
puts("> " + command + "\n")
pid, stdin, stdout, stderr = Open4::popen4(command)
while Process::waitpid(pid, Process::WNOHANG).nil? do
stdout.each_line { |line| puts line }
stderr.each_line { |line| puts line }
sleep(1)
end
stdout.each_line { |line| puts line }
stderr.each_line { |line| puts line }
end
# shell_exec("ls -l && sleep 5 && ls -l && sleep 2")
@rgaufman
Copy link

rgaufman commented May 8, 2018

Thank you for that, here is a similar one with Open3:

#!/usr/bin/env ruby
# frozen_string_literal: true

require 'open3'

def find
  Open3.popen3('find .') do |_stdin, stdout, stderr, wait_thr|
    pid = wait_thr.pid
    begin
      while Process.waitpid(pid, Process::WNOHANG).nil?
        stdout.each_line { |line| yield line.strip }
        stderr.each_line { |line| puts line.strip }
        sleep(0.5)
      end
    rescue Errno::ECHILD # in case process exits very quickly
    end
    stdout.each_line { |line| yield line.strip }
    stderr.each_line { |line| puts line.strip }
  end
end

find do |path|
  p path
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment