Method: IO.popen

Defined in:
io.c

.popen(env = {}, cmd, mode = 'r', **opts) ⇒ IO .popen(env = ) { ... } ⇒ Object

Executes the given command cmd as a subprocess whose $stdin and $stdout are connected to a new stream io.

This method has potential security vulnerabilities if called with untrusted input; see Command Injection.

If no block is given, returns the new stream, which depending on given mode may be open for reading, writing, or both. The stream should be explicitly closed (eventually) to avoid resource leaks.

If a block is given, the stream is passed to the block (again, open for reading, writing, or both); when the block exits, the stream is closed, and the block’s value is assigned to global variable $? and returned.

Optional argument mode may be any valid IO mode. See Access Modes.

Required argument cmd determines which of the following occurs:

  • The process forks.

  • A specified program runs in a shell.

  • A specified program runs with specified arguments.

  • A specified program runs with specified arguments and a specified argv0.

Each of these is detailed below.

The optional hash argument env specifies name/value pairs that are to be added to the environment variables for the subprocess:

IO.popen({'FOO' => 'bar'}, 'ruby', 'r+') do |pipe|
  pipe.puts 'puts ENV["FOO"]'
  pipe.close_write
  pipe.gets
end => "bar\n"

Optional keyword arguments opts specify:

Forked Process

When argument cmd is the 1-character string '-', causes the process to fork:

IO.popen('-') do |pipe|
  if pipe
    $stderr.puts "In parent, child pid is #{pipe.pid}\n"
  else
    $stderr.puts "In child, pid is #{$$}\n"
  end
end

Output:

In parent, child pid is 26253
In child, pid is 26253

Note that this is not supported on all platforms.

Shell Subprocess

When argument cmd is a single string (but not '-'), the program named cmd is run as a shell command:

IO.popen('uname') do |pipe|
  pipe.readlines
end

Output:

["Linux\n"]

Another example:

IO.popen('/bin/sh', 'r+') do |pipe|
  pipe.puts('ls')
  pipe.close_write
  $stderr.puts pipe.readlines.size
end

Output:

213

Program Subprocess

When argument cmd is an array of strings, the program named cmd[0] is run with all elements of cmd as its arguments:

IO.popen(['du', '..', '.']) do |pipe|
  $stderr.puts pipe.readlines.size
end

Output:

1111

Program Subprocess with argv0

When argument cmd is an array whose first element is a 2-element string array and whose remaining elements (if any) are strings:

  • cmd[0][0] (the first string in the nested array) is the name of a program that is run.

  • cmd[0][1] (the second string in the nested array) is set as the program’s argv[0].

  • cmd[1..-1] (the strings in the outer array) are the program’s arguments.

Example (sets $0 to ‘foo’):

IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"

Some Special Examples

# Set IO encoding.
IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  euc_jp_string = nkf_io.read
}

# Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) do |io|
  ls_result_with_error = io.read
end

# Use mixture of spawn options and IO options.
IO.popen(["ls", "/"], :err=>[:child, :out]) do |io|
  ls_result_with_error = io.read
end

 f = IO.popen("uname")
 p f.readlines
 f.close
 puts "Parent is #{Process.pid}"
 IO.popen("date") {|f| puts f.gets }
 IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
 p $?
 IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
   f.puts "bar"; f.close_write; puts f.gets
 }

Output (from last section):

["Linux\n"]
Parent is 21346
Thu Jan 15 22:41:19 JST 2009
21346 is here, f is #<IO:fd 3>
21352 is here, f is nil
#<Process::Status: pid 21352 exit 0>
<foo>bar;zot;

Raises exceptions that IO.pipe and Kernel.spawn raise.

Overloads:

  • .popen(env = {}, cmd, mode = 'r', **opts) ⇒ IO

    Returns:

  • .popen(env = ) { ... } ⇒ Object

    Yields:

    Returns:



7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
# File 'io.c', line 7982

static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
    VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;

    if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
    if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
    switch (argc) {
      case 2:
        pmode = argv[1];
      case 1:
        pname = argv[0];
        break;
      default:
        {
            int ex = !NIL_P(opt);
            rb_error_arity(argc + ex, 1 + ex, 2 + ex);
        }
    }
    return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
}