Created
December 10, 2016 22:36
-
-
Save JoshCheek/61769bfa05d52609e15948fabfad3381 to your computer and use it in GitHub Desktop.
A shell pipeline in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Read initial standard input from the data segment at the end of the file | |
# You can also see what is ultimately output down there | |
pos = DATA.pos # => 1617 | |
$stdin.reopen __FILE__ # => #<IO:/var/folders/7g/mbft22555w3_2nqs_h1kbglw0000gn/T/seeing_is_believing_temp_dir20161210-36802-czciw7/program.rb> | |
$stdin.seek pos, :SET # => 0 | |
# The commands that will be piped together | |
commands = [ | |
%w[cat], | |
%w[tr a A], | |
%w[tr c C], | |
] | |
# Connnect each command's to our stderr, first has our stdin, last has our stdout | |
pipeline = commands.map do |command| | |
{ command: command, | |
stdin: $stdin, | |
stdout: $stdout, | |
stderr: $stderr, | |
close_stdin: false, | |
close_stdout: false, | |
} | |
end | |
# Pipe each command's stdout to the next command's stdin | |
pipeline.each_cons(2) do |(left, right)| | |
right[:stdin], left[:stdout] = IO.pipe | |
right[:close_stdin] = true | |
left[:close_stdout] = true | |
end | |
# Execute each command | |
pipeline.each do |attrs| | |
# if we are the parent process | |
if pid = fork | |
# Document the pid, close the piped file descriptors, on to the next | |
attrs[:pid] = pid | |
attrs[:stdin].close if attrs[:close_stdin] | |
attrs[:stdout].close if attrs[:close_stdout] | |
next | |
end | |
# Subprocess sets the file descriptors and execs the command | |
STDIN.reopen attrs[:stdin] | |
STDOUT.reopen attrs[:stdout] | |
STDERR.reopen attrs[:stderr] | |
exec *attrs[:command] | |
end | |
# Wait for the children to finish, record their exit statuses | |
pipeline.each do |attrs| | |
Process.wait attrs[:pid] | |
attrs[:status] = $? | |
end | |
pipeline | |
# => [{:command=>["cat"], | |
# :stdin=> | |
# #<IO:/var/folders/7g/mbft22555w3_2nqs_h1kbglw0000gn/T/seeing_is_believing_temp_dir20161210-36802-czciw7/program.rb>, | |
# :stdout=>#<IO:(closed)>, | |
# :stderr=>#<IO:<STDERR>>, | |
# :close_stdin=>false, | |
# :close_stdout=>true, | |
# :pid=>36804, | |
# :status=>#<Process::Status: pid 36804 exit 0>}, | |
# {:command=>["tr", "a", "A"], | |
# :stdin=>#<IO:(closed)>, | |
# :stdout=>#<IO:(closed)>, | |
# :stderr=>#<IO:<STDERR>>, | |
# :close_stdin=>true, | |
# :close_stdout=>true, | |
# :pid=>36805, | |
# :status=>#<Process::Status: pid 36805 exit 0>}, | |
# {:command=>["tr", "c", "C"], | |
# :stdin=>#<IO:(closed)>, | |
# :stdout=>#<IO:<STDOUT>>, | |
# :stderr=>#<IO:<STDERR>>, | |
# :close_stdin=>true, | |
# :close_stdout=>false, | |
# :pid=>36806, | |
# :status=>#<Process::Status: pid 36806 exit 0>}] | |
# >> AAA | |
# >> bbb | |
# >> CCC | |
__END__ | |
aaa | |
bbb | |
ccc |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment