Open3 模組

Open3 模組支援建立子程序,並存取其 $stdin、$stdout 和 $stderr 串流。

此處內容

這些方法會在新程序或子殼中執行給定的指令,或在新程序和/或子殼中執行多個指令

以上每種方法都接受

常數

VERSION

公開類別方法

capture2([env, ] command_line, options = {}) → [stdout_s, status] 按一下以切換來源
capture2([env, ] exe_path, *args, options = {}) → [stdout_s, status]

基本上是 Open3.popen3 的包裝器,它

  • 透過使用提供的引數(雜湊 options 中的特定項目除外;請參閱下方)呼叫 Open3.popen3 來建立子處理程序。

  • 將子處理程序的標準輸出作為字串 stdout_s 傳回。

  • Process::Status 物件作為 status 傳回,它代表子處理程序的結束狀態。

傳回陣列 [stdout_s, status]

stdout_s, status = Open3.capture2('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326047 exit 0>]

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會成為呼叫 Open3.popen3 時的領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會成為呼叫 Open3.popen3 時的尾隨引數 options;請參閱 執行選項

提供雜湊 options;兩個選項在方法 Open3.capture2 中具有區域效果

  • 如果項目 options[:stdin_data] 存在,則移除該項目,並將其字串值傳送至命令的標準輸入

    Open3.capture2('tee', stdin_data: 'Foo')
    
    # => ["Foo", #<Process::Status: pid 2326087 exit 0>]
    
  • 如果項目 options[:binmode] 存在,則移除該項目,並將內部串流設定為二進位模式。

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.capture2('if true; then echo "Foo"; fi') # Shell reserved word.
# => ["Foo\n", #<Process::Status: pid 2326131 exit 0>]
Open3.capture2('echo')                         # Built-in.
# => ["\n", #<Process::Status: pid 2326139 exit 0>]
Open3.capture2('date > date.tmp')              # Contains meta character.
# => ["", #<Process::Status: pid 2326174 exit 0>]

命令列也可能包含命令的引數和選項

Open3.capture2('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326183 exit 0>]

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.capture2('/usr/bin/date')
# => ["Fri Sep 29 01:00:39 PM CDT 2023\n", #<Process::Status: pid 2326222 exit 0>]

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.capture2('doesnt_exist') # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.capture2('echo', 'C #')
# => ["C #\n", #<Process::Status: pid 2326267 exit 0>]
Open3.capture2('echo', 'hello', 'world')
# => ["hello world\n", #<Process::Status: pid 2326299 exit 0>]
# File lib/open3.rb, line 775
def capture2(*cmd)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  stdin_data = opts.delete(:stdin_data)
  binmode = opts.delete(:binmode)

  popen2(*cmd, opts) {|i, o, t|
    if binmode
      i.binmode
      o.binmode
    end
    out_reader = Thread.new { o.read }
    if stdin_data
      begin
        if stdin_data.respond_to? :readpartial
          IO.copy_stream(stdin_data, i)
        else
          i.write stdin_data
        end
      rescue Errno::EPIPE
      end
    end
    i.close
    [out_reader.value, t.value]
  }
end
capture2e([env, ] command_line, options = {}) → [stdout_and_stderr_s, status] 按一下以切換來源
capture2e([env, ] exe_path, *args, options = {}) → [stdout_and_stderr_s, status]

基本上是 Open3.popen3 的包裝器,它

  • 透過使用提供的引數(雜湊 options 中的特定項目除外;請參閱下方)呼叫 Open3.popen3 來建立子處理程序。

  • 傳回合併的子處理程序標準輸出和標準錯誤的字串 stdout_and_stderr_s

  • Process::Status 物件作為 status 傳回,它代表子處理程序的結束狀態。

傳回陣列 [stdout_and_stderr_s, status]

stdout_and_stderr_s, status = Open3.capture2e('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2371692 exit 0>]

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會成為呼叫 Open3.popen3 時的領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會成為呼叫 Open3.popen3 時的尾隨引數 options;請參閱 執行選項

給定雜湊 options;兩個選項在方法 Open3.capture2e 中具有局部效果

  • 如果項目 options[:stdin_data] 存在,則移除該項目,並將其字串值傳送至命令的標準輸入

    Open3.capture2e('tee', stdin_data: 'Foo')
    # => ["Foo", #<Process::Status: pid 2371732 exit 0>]
    
  • 如果項目 options[:binmode] 存在,則移除該項目,並將內部串流設定為二進位模式。

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.capture2e('if true; then echo "Foo"; fi') # Shell reserved word.
# => ["Foo\n", #<Process::Status: pid 2371740 exit 0>]
Open3.capture2e('echo')                         # Built-in.
# => ["\n", #<Process::Status: pid 2371774 exit 0>]
Open3.capture2e('date > date.tmp')              # Contains meta character.
# => ["", #<Process::Status: pid 2371812 exit 0>]

命令列也可能包含命令的引數和選項

Open3.capture2e('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326183 exit 0>]

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.capture2e('/usr/bin/date')
# => ["Sat Sep 30 09:01:46 AM CDT 2023\n", #<Process::Status: pid 2371820 exit 0>]

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.capture2e('doesnt_exist') # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.capture2e('echo', 'C #')
# => ["C #\n", #<Process::Status: pid 2371856 exit 0>]
Open3.capture2e('echo', 'hello', 'world')
# => ["hello world\n", #<Process::Status: pid 2371894 exit 0>]
# File lib/open3.rb, line 902
def capture2e(*cmd)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  stdin_data = opts.delete(:stdin_data)
  binmode = opts.delete(:binmode)

  popen2e(*cmd, opts) {|i, oe, t|
    if binmode
      i.binmode
      oe.binmode
    end
    outerr_reader = Thread.new { oe.read }
    if stdin_data
      begin
        if stdin_data.respond_to? :readpartial
          IO.copy_stream(stdin_data, i)
        else
          i.write stdin_data
        end
      rescue Errno::EPIPE
      end
    end
    i.close
    [outerr_reader.value, t.value]
  }
end
capture3([env, ] command_line, options = {}) → [stdout_s, stderr_s, status] 按一下以切換來源
capture3([env, ] exe_path, *args, options = {}) → [stdout_s, stderr_s, status]

基本上是 Open3.popen3 的包裝器,它

  • 透過使用提供的引數(雜湊 options 中的特定項目除外;請參閱下方)呼叫 Open3.popen3 來建立子處理程序。

  • 傳回子處理程序的標準輸出和標準錯誤的字串 stdout_sstderr_s

  • Process::Status 物件作為 status 傳回,它代表子處理程序的結束狀態。

傳回陣列 [stdout_s, stderr_s, status]

stdout_s, stderr_s, status = Open3.capture3('echo "Foo"')
# => ["Foo\n", "", #<Process::Status: pid 2281954 exit 0>]

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會成為呼叫 Open3.popen3 時的領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會成為呼叫 Open3.popen3 時的尾隨引數 options;請參閱 執行選項

給定雜湊 options;兩個選項在方法 Open3.capture3 中具有局部效果

  • 如果項目 options[:stdin_data] 存在,則移除該項目,並將其字串值傳送至命令的標準輸入

    Open3.capture3('tee', stdin_data: 'Foo')
    # => ["Foo", "", #<Process::Status: pid 2319575 exit 0>]
    
  • 如果項目 options[:binmode] 存在,則移除該項目,並將內部串流設定為二進位模式。

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.capture3('if true; then echo "Foo"; fi') # Shell reserved word.
# => ["Foo\n", "", #<Process::Status: pid 2282025 exit 0>]
Open3.capture3('echo')                         # Built-in.
# => ["\n", "", #<Process::Status: pid 2282092 exit 0>]
Open3.capture3('date > date.tmp')              # Contains meta character.
# => ["", "", #<Process::Status: pid 2282110 exit 0>]

命令列也可能包含命令的引數和選項

Open3.capture3('echo "Foo"')
# => ["Foo\n", "", #<Process::Status: pid 2282092 exit 0>]

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.capture3('/usr/bin/date')
# => ["Thu Sep 28 05:03:51 PM CDT 2023\n", "", #<Process::Status: pid 2282300 exit 0>]

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.capture3('doesnt_exist') # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.capture3('echo', 'C #')
# => ["C #\n", "", #<Process::Status: pid 2282368 exit 0>]
Open3.capture3('echo', 'hello', 'world')
# => ["hello world\n", "", #<Process::Status: pid 2282372 exit 0>]
# File lib/open3.rb, line 648
def capture3(*cmd)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  stdin_data = opts.delete(:stdin_data) || ''
  binmode = opts.delete(:binmode)

  popen3(*cmd, opts) {|i, o, e, t|
    if binmode
      i.binmode
      o.binmode
      e.binmode
    end
    out_reader = Thread.new { o.read }
    err_reader = Thread.new { e.read }
    begin
      if stdin_data.respond_to? :readpartial
        IO.copy_stream(stdin_data, i)
      else
        i.write stdin_data
      end
    rescue Errno::EPIPE
    end
    i.close
    [out_reader.value, err_reader.value, t.value]
  }
end
pipeline([env, ] *cmds, options = {}) → array_of_statuses 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 管線傳遞到下一個子程序的 stdin,或對於最後一個子程序,傳遞到呼叫者的 stdout

  • 等待子程序結束。

  • 傳回 Process::Status 物件的陣列(每個子程序一個)。

範例

wait_threads = Open3.pipeline('ls', 'grep R')
# => [#<Process::Status: pid 2139200 exit 0>, #<Process::Status: pid 2139202 exit 0>]

輸出

Rakefile
README.md

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1334
def pipeline(*cmds)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  pipeline_run(cmds, opts, [], []) {|ts|
    ts.map(&:value)
  }
end
pipeline_r([env, ] *cmds, options = {}) → [last_stdout, wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 管線傳遞到下一個子程序的 stdin,或對於最後一個子程序,傳遞到呼叫者的 stdout

此方法不會等待子程序結束,因此呼叫者必須這麼做。

如果沒有提供區塊,會傳回包含下列 2 個元素的陣列:

  • 最後一個子程序的 stdout 串流。

  • 所有子程序的等待執行緒陣列。

範例

last_stdout, wait_threads = Open3.pipeline_r('ls', 'grep R')
# => [#<IO:fd 5>, [#<Process::Waiter:0x000055e8de2f9898 dead>, #<Process::Waiter:0x000055e8de2f94b0 sleep>]]
puts last_stdout.read
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

Rakefile
README.md

如果提供區塊,會使用最後一個子程序的 stdout 串流和等待程序陣列呼叫區塊。

Open3.pipeline_r('ls', 'grep R') do |last_stdout, wait_threads|
  puts last_stdout.read
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

Rakefile
README.md

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1104
def pipeline_r(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  pipeline_run(cmds, opts, [out_w], [out_r], &block)
end
pipeline_rw([env, ] *cmds, options = {}) → [first_stdin, last_stdout, wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 管線傳遞到下一個子程序的 stdin,或對於第一個子程序,從呼叫者的 stdin,或對於最後一個子程序,傳遞到呼叫者的 stdout

此方法不會等待子程序結束,因此呼叫者必須這麼做。

如果沒有提供區塊,會傳回包含下列 3 個元素的陣列:

  • 第一個子程序的 stdin 串流。

  • 最後一個子程序的 stdout 串流。

  • 所有子程序的等待執行緒陣列。

範例

first_stdin, last_stdout, wait_threads = Open3.pipeline_rw('sort', 'cat -n')
# => [#<IO:fd 20>, #<IO:fd 21>, [#<Process::Waiter:0x000055e8de29ab40 sleep>, #<Process::Waiter:0x000055e8de29a690 sleep>]]
first_stdin.puts("foo\nbar\nbaz")
first_stdin.close # Send EOF to sort.
puts last_stdout.read
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

1 bar
2 baz
3 foo

給定一個區塊,使用第一個子程序的 stdin 串流、最後一個子程序的 stdout 串流,以及等待程序的陣列呼叫該區塊。

Open3.pipeline_rw('sort', 'cat -n') do |first_stdin, last_stdout, wait_threads|
  first_stdin.puts "foo\nbar\nbaz"
  first_stdin.close # send EOF to sort.
  puts last_stdout.read
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

1 bar
2 baz
3 foo

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1014
def pipeline_rw(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block)
end
pipeline_start([env, ] *cmds, options = {}) → [wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 不等待子程序結束。

如果沒有給定區塊,則傳回所有子程序的等待執行緒陣列。

範例

wait_threads = Open3.pipeline_start('ls', 'grep R')
# => [#<Process::Waiter:0x000055e8de9d2bb0 run>, #<Process::Waiter:0x000055e8de9d2890 run>]
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

Rakefile
README.md

給定一個區塊,使用等待程序的陣列呼叫該區塊。

Open3.pipeline_start('ls', 'grep R') do |wait_threads|
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

Rakefile
README.md

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1272
def pipeline_start(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  if block
    pipeline_run(cmds, opts, [], [], &block)
  else
    ts, = pipeline_run(cmds, opts, [], [])
    ts
  end
end
pipeline_w([env, ] *cmds, options = {}) → [first_stdin, wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 導管到下一個子程序的 stdin,或者,對於第一個子程序,將呼叫者的 stdout 導管到子程序的 stdin

此方法不會等待子程序結束,因此呼叫者必須這麼做。

如果沒有提供區塊,會傳回包含下列 2 個元素的陣列:

  • 第一個子程序的 stdin 串流。

  • 所有子程序的等待執行緒陣列。

範例

first_stdin, wait_threads = Open3.pipeline_w('sort', 'cat -n')
# => [#<IO:fd 7>, [#<Process::Waiter:0x000055e8de928278 run>, #<Process::Waiter:0x000055e8de923e80 run>]]
first_stdin.puts("foo\nbar\nbaz")
first_stdin.close # Send EOF to sort.
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

1 bar
2 baz
3 foo

給定一個區塊,使用第一個子程序的 stdin 串流,以及等待程序的陣列呼叫該區塊。

Open3.pipeline_w('sort', 'cat -n') do |first_stdin, wait_threads|
  first_stdin.puts("foo\nbar\nbaz")
  first_stdin.close # Send EOF to sort.
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

1 bar
2 baz
3 foo

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1195
def pipeline_w(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  pipeline_run(cmds, opts, [in_r], [in_w], &block)
end
popen2([env, ] command_line, options = {}) → [stdin, stdout, wait_thread] 按一下以切換來源
popen2([env, ] exe_path, *args, options = {}) → [stdin, stdout, wait_thread]
popen2([env, ] command_line, options = {}) {|stdin, stdout, wait_thread| ... } → object
popen2([env, ] exe_path, *args, options = {}) {|stdin, stdout, wait_thread| ... } → object

基本上是 Process.spawn 的包裝器,它

  • 透過使用給定的引數呼叫 Process.spawn 來建立子程序。

  • 建立串流 stdinstdout,它們是子程序中的標準輸入和標準輸出串流。

  • 建立執行緒 wait_thread,等待子程序結束;該執行緒有方法 pid,它傳回子程序的程序識別碼。

如果沒有給定區塊,則傳回陣列 [stdin, stdout, wait_thread]。呼叫者應關閉兩個傳回的串流。

stdin, stdout, wait_thread = Open3.popen2('echo')
# => [#<IO:fd 6>, #<IO:fd 7>, #<Process::Waiter:0x00007f58d52dbe98 run>]
stdin.close
stdout.close
wait_thread.pid   # => 2263572
wait_thread.value # => #<Process::Status: pid 2263572 exit 0>

給定一個區塊,使用三個變數(兩個串流和等待執行緒)呼叫該區塊,並傳回區塊的傳回值。呼叫者不需要關閉串流。

Open3.popen2('echo') do |stdin, stdout, wait_thread|
  p stdin
  p stdout
  p wait_thread
  p wait_thread.pid
  p wait_thread.value
end

輸出

#<IO:fd 6>
#<IO:fd 7>
#<Process::Waiter:0x00007f58d59a34b0 sleep>
2263636
#<Process::Status: pid 2263636 exit 0>

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會在呼叫 Process.spawn 時,變成領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會在呼叫 Process.spawn 時,變成尾隨引數 options;請參閱 執行選項

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.popen2('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
Open3.popen2('echo') {|*args| p args }                         # Built-in.
Open3.popen2('date > date.tmp') {|*args| p args }              # Contains meta character.

輸出(對於上述每個呼叫都類似)

# => [#<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f7577dfe410 dead>]

命令列也可能包含命令的引數和選項

Open3.popen2('echo "Foo"') { |i, o, t| o.gets }
"Foo\n"

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.popen2('/usr/bin/date') { |i, o, t| o.gets }
# => "Thu Sep 28 09:41:06 AM CDT 2023\n"

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.popen2('doesnt_exist') { |i, o, t| o.gets } # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.popen2('echo', 'C #') { |i, o, t| o.gets }
# => "C #\n"
Open3.popen2('echo', 'hello', 'world') { |i, o, t| o.gets }
# => "hello world\n"

相關

  • Open3.popen2e:使子處理程序的標準輸入和標準輸出與標準錯誤串流的合併可用於個別串流。

  • Open3.popen3:使子處理程序的標準輸入、標準輸出和標準錯誤串流可用於個別串流。

# File lib/open3.rb, line 365
def popen2(*cmd, &block)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
end
popen2e([env, ] command_line, options = {}) → [stdin, stdout_and_stderr, wait_thread] 按一下以切換來源
popen2e([env, ] exe_path, *args, options = {}) → [stdin, stdout_and_stderr, wait_thread]
popen2e([env, ] command_line, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } → object
popen2e([env, ] exe_path, *args, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } → object

基本上是 Process.spawn 的包裝器,它

  • 透過使用給定的引數呼叫 Process.spawn 來建立子程序。

  • 建立串流 stdinstdout_and_stderr,它們是子處理程序中的標準輸入和標準輸出與標準錯誤串流的合併。

  • 建立執行緒 wait_thread,等待子程序結束;該執行緒有方法 pid,它傳回子程序的程序識別碼。

如果沒有給定區塊,則傳回陣列 [stdin, stdout_and_stderr, wait_thread]。呼叫者應關閉兩個傳回的串流。

stdin, stdout_and_stderr, wait_thread = Open3.popen2e('echo')
# => [#<IO:fd 6>, #<IO:fd 7>, #<Process::Waiter:0x00007f7577da4398 run>]
stdin.close
stdout_and_stderr.close
wait_thread.pid   # => 2274600
wait_thread.value # => #<Process::Status: pid 2274600 exit 0>

給定一個區塊,使用三個變數(兩個串流和等待執行緒)呼叫該區塊,並傳回區塊的傳回值。呼叫者不需要關閉串流。

Open3.popen2e('echo') do |stdin, stdout_and_stderr, wait_thread|
  p stdin
  p stdout_and_stderr
  p wait_thread
  p wait_thread.pid
  p wait_thread.value
end

輸出

#<IO:fd 6>
#<IO:fd 7>
#<Process::Waiter:0x00007f75777578c8 sleep>
2274763
#<Process::Status: pid 2274763 exit 0>

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會在呼叫 Process.spawn 時,變成領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會在呼叫 Process.spawn 時,變成尾隨引數 options;請參閱 執行選項

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.popen2e('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
Open3.popen2e('echo') {|*args| p args }                         # Built-in.
Open3.popen2e('date > date.tmp') {|*args| p args }              # Contains meta character.

輸出(對於上述每個呼叫都類似)

# => [#<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f7577d8a1f0 dead>]

命令列也可能包含命令的引數和選項

Open3.popen2e('echo "Foo"') { |i, o_and_e, t| o_and_e.gets }
"Foo\n"

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.popen2e('/usr/bin/date') { |i, o_and_e, t| o_and_e.gets }
# => "Thu Sep 28 01:58:45 PM CDT 2023\n"

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.popen2e('doesnt_exist') { |i, o_and_e, t| o_and_e.gets } # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.popen2e('echo', 'C #') { |i, o_and_e, t| o_and_e.gets }
# => "C #\n"
Open3.popen2e('echo', 'hello', 'world') { |i, o_and_e, t| o_and_e.gets }
# => "hello world\n"

相關

  • Open3.popen2:使子處理程序的標準輸入和標準輸出串流可用於個別串流,但無法存取標準錯誤串流。

  • Open3.popen3:使子處理程序的標準輸入、標準輸出和標準錯誤串流可用於個別串流。

# File lib/open3.rb, line 508
def popen2e(*cmd, &block)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[[:out, :err]] = out_w

  popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
ensure
  if block
    in_r.close
    in_w.close
    out_r.close
    out_w.close
  end
end
popen3([env, ] command_line, options = {}) → [stdin, stdout, stderr, wait_thread] 按一下以切換來源
popen3([env, ] exe_path, *args, options = {}) → [stdin, stdout, stderr, wait_thread]
popen3([env, ] command_line, options = {}) {|stdin, stdout, stderr, wait_thread| ... } → object
popen3([env, ] exe_path, *args, options = {}) {|stdin, stdout, stderr, wait_thread| ... } → object

基本上是 Process.spawn 的包裝器,它

  • 透過使用給定的引數呼叫 Process.spawn 來建立子程序。

  • 建立串流 stdinstdoutstderr,它們是子處理程序中的標準輸入、標準輸出和標準錯誤串流。

  • 建立執行緒 wait_thread,等待子程序結束;該執行緒有方法 pid,它傳回子程序的程序識別碼。

如果沒有給定區塊,則傳回陣列 [stdin, stdout, stderr, wait_thread]。呼叫者應關閉三個傳回的串流。

stdin, stdout, stderr, wait_thread = Open3.popen3('echo')
# => [#<IO:fd 8>, #<IO:fd 10>, #<IO:fd 12>, #<Process::Waiter:0x00007f58d5428f58 run>]
stdin.close
stdout.close
stderr.close
wait_thread.pid   # => 2210481
wait_thread.value # => #<Process::Status: pid 2210481 exit 0>

如果給定區塊,則使用四個變數(三個串流和等待執行緒)呼叫區塊,並傳回區塊的傳回值。呼叫者不需要關閉串流

Open3.popen3('echo') do |stdin, stdout, stderr, wait_thread|
  p stdin
  p stdout
  p stderr
  p wait_thread
  p wait_thread.pid
  p wait_thread.value
end

輸出

#<IO:fd 6>
#<IO:fd 7>
#<IO:fd 9>
#<Process::Waiter:0x00007f58d53606e8 sleep>
2211047
#<Process::Status: pid 2211047 exit 0>

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會在呼叫 Process.spawn 時,變成領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會在呼叫 Process.spawn 時,變成尾隨引數 options;請參閱 執行選項

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.popen3('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
Open3.popen3('echo') {|*args| p args }                         # Built-in.
Open3.popen3('date > date.tmp') {|*args| p args }              # Contains meta character.

輸出(對於上述每個呼叫都類似)

[#<IO:(closed)>, #<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f58d52f28c8 dead>]

命令列也可能包含命令的引數和選項

Open3.popen3('echo "Foo"') { |i, o, e, t| o.gets }
"Foo\n"

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.popen3('/usr/bin/date') { |i, o, e, t| o.gets }
# => "Wed Sep 27 02:56:44 PM CDT 2023\n"

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.popen3('doesnt_exist') { |i, o, e, t| o.gets } # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.popen3('echo', 'C #') { |i, o, e, t| o.gets }
# => "C #\n"
Open3.popen3('echo', 'hello', 'world') { |i, o, e, t| o.gets }
# => "hello world\n"

小心避免死結。輸出串流 stdoutstderr 有固定大小的緩衝區,所以大量讀取其中一個但未讀取另一個,當未讀取的緩衝區填滿時可能會造成死結。為避免這種情況,stdoutstderr 應同時讀取(使用執行緒或 IO.select)。

相關

  • Open3.popen2:使子處理程序的標準輸入和標準輸出串流可用於個別串流,但無法存取標準錯誤串流。

  • Open3.popen2e:使子處理程序的標準輸入和標準輸出與標準錯誤串流的合併可用於個別串流。

# File lib/open3.rb, line 218
def popen3(*cmd, &block)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  err_r, err_w = IO.pipe
  opts[:err] = err_w

  popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block)
end

私人實例方法

capture2([env, ] command_line, options = {}) → [stdout_s, status] 按一下以切換來源
capture2([env, ] exe_path, *args, options = {}) → [stdout_s, status]

基本上是 Open3.popen3 的包裝器,它

  • 透過使用提供的引數(雜湊 options 中的特定項目除外;請參閱下方)呼叫 Open3.popen3 來建立子處理程序。

  • 將子處理程序的標準輸出作為字串 stdout_s 傳回。

  • Process::Status 物件作為 status 傳回,它代表子處理程序的結束狀態。

傳回陣列 [stdout_s, status]

stdout_s, status = Open3.capture2('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326047 exit 0>]

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會成為呼叫 Open3.popen3 時的領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會成為呼叫 Open3.popen3 時的尾隨引數 options;請參閱 執行選項

提供雜湊 options;兩個選項在方法 Open3.capture2 中具有區域效果

  • 如果項目 options[:stdin_data] 存在,則移除該項目,並將其字串值傳送至命令的標準輸入

    Open3.capture2('tee', stdin_data: 'Foo')
    
    # => ["Foo", #<Process::Status: pid 2326087 exit 0>]
    
  • 如果項目 options[:binmode] 存在,則移除該項目,並將內部串流設定為二進位模式。

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.capture2('if true; then echo "Foo"; fi') # Shell reserved word.
# => ["Foo\n", #<Process::Status: pid 2326131 exit 0>]
Open3.capture2('echo')                         # Built-in.
# => ["\n", #<Process::Status: pid 2326139 exit 0>]
Open3.capture2('date > date.tmp')              # Contains meta character.
# => ["", #<Process::Status: pid 2326174 exit 0>]

命令列也可能包含命令的引數和選項

Open3.capture2('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326183 exit 0>]

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.capture2('/usr/bin/date')
# => ["Fri Sep 29 01:00:39 PM CDT 2023\n", #<Process::Status: pid 2326222 exit 0>]

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.capture2('doesnt_exist') # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.capture2('echo', 'C #')
# => ["C #\n", #<Process::Status: pid 2326267 exit 0>]
Open3.capture2('echo', 'hello', 'world')
# => ["hello world\n", #<Process::Status: pid 2326299 exit 0>]
# File lib/open3.rb, line 775
def capture2(*cmd)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  stdin_data = opts.delete(:stdin_data)
  binmode = opts.delete(:binmode)

  popen2(*cmd, opts) {|i, o, t|
    if binmode
      i.binmode
      o.binmode
    end
    out_reader = Thread.new { o.read }
    if stdin_data
      begin
        if stdin_data.respond_to? :readpartial
          IO.copy_stream(stdin_data, i)
        else
          i.write stdin_data
        end
      rescue Errno::EPIPE
      end
    end
    i.close
    [out_reader.value, t.value]
  }
end
capture2e([env, ] command_line, options = {}) → [stdout_and_stderr_s, status] 按一下以切換來源
capture2e([env, ] exe_path, *args, options = {}) → [stdout_and_stderr_s, status]

基本上是 Open3.popen3 的包裝器,它

  • 透過使用提供的引數(雜湊 options 中的特定項目除外;請參閱下方)呼叫 Open3.popen3 來建立子處理程序。

  • 傳回合併的子處理程序標準輸出和標準錯誤的字串 stdout_and_stderr_s

  • Process::Status 物件作為 status 傳回,它代表子處理程序的結束狀態。

傳回陣列 [stdout_and_stderr_s, status]

stdout_and_stderr_s, status = Open3.capture2e('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2371692 exit 0>]

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會成為呼叫 Open3.popen3 時的領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會成為呼叫 Open3.popen3 時的尾隨引數 options;請參閱 執行選項

給定雜湊 options;兩個選項在方法 Open3.capture2e 中具有局部效果

  • 如果項目 options[:stdin_data] 存在,則移除該項目,並將其字串值傳送至命令的標準輸入

    Open3.capture2e('tee', stdin_data: 'Foo')
    # => ["Foo", #<Process::Status: pid 2371732 exit 0>]
    
  • 如果項目 options[:binmode] 存在,則移除該項目,並將內部串流設定為二進位模式。

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.capture2e('if true; then echo "Foo"; fi') # Shell reserved word.
# => ["Foo\n", #<Process::Status: pid 2371740 exit 0>]
Open3.capture2e('echo')                         # Built-in.
# => ["\n", #<Process::Status: pid 2371774 exit 0>]
Open3.capture2e('date > date.tmp')              # Contains meta character.
# => ["", #<Process::Status: pid 2371812 exit 0>]

命令列也可能包含命令的引數和選項

Open3.capture2e('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326183 exit 0>]

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.capture2e('/usr/bin/date')
# => ["Sat Sep 30 09:01:46 AM CDT 2023\n", #<Process::Status: pid 2371820 exit 0>]

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.capture2e('doesnt_exist') # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.capture2e('echo', 'C #')
# => ["C #\n", #<Process::Status: pid 2371856 exit 0>]
Open3.capture2e('echo', 'hello', 'world')
# => ["hello world\n", #<Process::Status: pid 2371894 exit 0>]
# File lib/open3.rb, line 902
def capture2e(*cmd)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  stdin_data = opts.delete(:stdin_data)
  binmode = opts.delete(:binmode)

  popen2e(*cmd, opts) {|i, oe, t|
    if binmode
      i.binmode
      oe.binmode
    end
    outerr_reader = Thread.new { oe.read }
    if stdin_data
      begin
        if stdin_data.respond_to? :readpartial
          IO.copy_stream(stdin_data, i)
        else
          i.write stdin_data
        end
      rescue Errno::EPIPE
      end
    end
    i.close
    [outerr_reader.value, t.value]
  }
end
capture3([env, ] command_line, options = {}) → [stdout_s, stderr_s, status] 按一下以切換來源
capture3([env, ] exe_path, *args, options = {}) → [stdout_s, stderr_s, status]

基本上是 Open3.popen3 的包裝器,它

  • 透過使用提供的引數(雜湊 options 中的特定項目除外;請參閱下方)呼叫 Open3.popen3 來建立子處理程序。

  • 傳回子處理程序的標準輸出和標準錯誤的字串 stdout_sstderr_s

  • Process::Status 物件作為 status 傳回,它代表子處理程序的結束狀態。

傳回陣列 [stdout_s, stderr_s, status]

stdout_s, stderr_s, status = Open3.capture3('echo "Foo"')
# => ["Foo\n", "", #<Process::Status: pid 2281954 exit 0>]

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會成為呼叫 Open3.popen3 時的領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會成為呼叫 Open3.popen3 時的尾隨引數 options;請參閱 執行選項

給定雜湊 options;兩個選項在方法 Open3.capture3 中具有局部效果

  • 如果項目 options[:stdin_data] 存在,則移除該項目,並將其字串值傳送至命令的標準輸入

    Open3.capture3('tee', stdin_data: 'Foo')
    # => ["Foo", "", #<Process::Status: pid 2319575 exit 0>]
    
  • 如果項目 options[:binmode] 存在,則移除該項目,並將內部串流設定為二進位模式。

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.capture3('if true; then echo "Foo"; fi') # Shell reserved word.
# => ["Foo\n", "", #<Process::Status: pid 2282025 exit 0>]
Open3.capture3('echo')                         # Built-in.
# => ["\n", "", #<Process::Status: pid 2282092 exit 0>]
Open3.capture3('date > date.tmp')              # Contains meta character.
# => ["", "", #<Process::Status: pid 2282110 exit 0>]

命令列也可能包含命令的引數和選項

Open3.capture3('echo "Foo"')
# => ["Foo\n", "", #<Process::Status: pid 2282092 exit 0>]

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.capture3('/usr/bin/date')
# => ["Thu Sep 28 05:03:51 PM CDT 2023\n", "", #<Process::Status: pid 2282300 exit 0>]

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.capture3('doesnt_exist') # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.capture3('echo', 'C #')
# => ["C #\n", "", #<Process::Status: pid 2282368 exit 0>]
Open3.capture3('echo', 'hello', 'world')
# => ["hello world\n", "", #<Process::Status: pid 2282372 exit 0>]
# File lib/open3.rb, line 648
def capture3(*cmd)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  stdin_data = opts.delete(:stdin_data) || ''
  binmode = opts.delete(:binmode)

  popen3(*cmd, opts) {|i, o, e, t|
    if binmode
      i.binmode
      o.binmode
      e.binmode
    end
    out_reader = Thread.new { o.read }
    err_reader = Thread.new { e.read }
    begin
      if stdin_data.respond_to? :readpartial
        IO.copy_stream(stdin_data, i)
      else
        i.write stdin_data
      end
    rescue Errno::EPIPE
    end
    i.close
    [out_reader.value, err_reader.value, t.value]
  }
end
pipeline([env, ] *cmds, options = {}) → array_of_statuses 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 管線傳遞到下一個子程序的 stdin,或對於最後一個子程序,傳遞到呼叫者的 stdout

  • 等待子程序結束。

  • 傳回 Process::Status 物件的陣列(每個子程序一個)。

範例

wait_threads = Open3.pipeline('ls', 'grep R')
# => [#<Process::Status: pid 2139200 exit 0>, #<Process::Status: pid 2139202 exit 0>]

輸出

Rakefile
README.md

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1334
def pipeline(*cmds)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  pipeline_run(cmds, opts, [], []) {|ts|
    ts.map(&:value)
  }
end
pipeline_r([env, ] *cmds, options = {}) → [last_stdout, wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 管線傳遞到下一個子程序的 stdin,或對於最後一個子程序,傳遞到呼叫者的 stdout

此方法不會等待子程序結束,因此呼叫者必須這麼做。

如果沒有提供區塊,會傳回包含下列 2 個元素的陣列:

  • 最後一個子程序的 stdout 串流。

  • 所有子程序的等待執行緒陣列。

範例

last_stdout, wait_threads = Open3.pipeline_r('ls', 'grep R')
# => [#<IO:fd 5>, [#<Process::Waiter:0x000055e8de2f9898 dead>, #<Process::Waiter:0x000055e8de2f94b0 sleep>]]
puts last_stdout.read
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

Rakefile
README.md

如果提供區塊,會使用最後一個子程序的 stdout 串流和等待程序陣列呼叫區塊。

Open3.pipeline_r('ls', 'grep R') do |last_stdout, wait_threads|
  puts last_stdout.read
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

Rakefile
README.md

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1104
def pipeline_r(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  pipeline_run(cmds, opts, [out_w], [out_r], &block)
end
pipeline_rw([env, ] *cmds, options = {}) → [first_stdin, last_stdout, wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 管線傳遞到下一個子程序的 stdin,或對於第一個子程序,從呼叫者的 stdin,或對於最後一個子程序,傳遞到呼叫者的 stdout

此方法不會等待子程序結束,因此呼叫者必須這麼做。

如果沒有提供區塊,會傳回包含下列 3 個元素的陣列:

  • 第一個子程序的 stdin 串流。

  • 最後一個子程序的 stdout 串流。

  • 所有子程序的等待執行緒陣列。

範例

first_stdin, last_stdout, wait_threads = Open3.pipeline_rw('sort', 'cat -n')
# => [#<IO:fd 20>, #<IO:fd 21>, [#<Process::Waiter:0x000055e8de29ab40 sleep>, #<Process::Waiter:0x000055e8de29a690 sleep>]]
first_stdin.puts("foo\nbar\nbaz")
first_stdin.close # Send EOF to sort.
puts last_stdout.read
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

1 bar
2 baz
3 foo

給定一個區塊,使用第一個子程序的 stdin 串流、最後一個子程序的 stdout 串流,以及等待程序的陣列呼叫該區塊。

Open3.pipeline_rw('sort', 'cat -n') do |first_stdin, last_stdout, wait_threads|
  first_stdin.puts "foo\nbar\nbaz"
  first_stdin.close # send EOF to sort.
  puts last_stdout.read
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

1 bar
2 baz
3 foo

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1014
def pipeline_rw(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block)
end
pipeline_start([env, ] *cmds, options = {}) → [wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 不等待子程序結束。

如果沒有給定區塊,則傳回所有子程序的等待執行緒陣列。

範例

wait_threads = Open3.pipeline_start('ls', 'grep R')
# => [#<Process::Waiter:0x000055e8de9d2bb0 run>, #<Process::Waiter:0x000055e8de9d2890 run>]
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

Rakefile
README.md

給定一個區塊,使用等待程序的陣列呼叫該區塊。

Open3.pipeline_start('ls', 'grep R') do |wait_threads|
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

Rakefile
README.md

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1272
def pipeline_start(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  if block
    pipeline_run(cmds, opts, [], [], &block)
  else
    ts, = pipeline_run(cmds, opts, [], [])
    ts
  end
end
pipeline_w([env, ] *cmds, options = {}) → [first_stdin, wait_threads] 按一下以切換來源

基本上是 Process.spawn 的包裝器,它

  • 透過呼叫 Process.spawn 為每個指定的 cmds 建立一個子程序。

  • 將每個子程序的 stdout 導管到下一個子程序的 stdin,或者,對於第一個子程序,將呼叫者的 stdout 導管到子程序的 stdin

此方法不會等待子程序結束,因此呼叫者必須這麼做。

如果沒有提供區塊,會傳回包含下列 2 個元素的陣列:

  • 第一個子程序的 stdin 串流。

  • 所有子程序的等待執行緒陣列。

範例

first_stdin, wait_threads = Open3.pipeline_w('sort', 'cat -n')
# => [#<IO:fd 7>, [#<Process::Waiter:0x000055e8de928278 run>, #<Process::Waiter:0x000055e8de923e80 run>]]
first_stdin.puts("foo\nbar\nbaz")
first_stdin.close # Send EOF to sort.
wait_threads.each do |wait_thread|
  wait_thread.join
end

輸出

1 bar
2 baz
3 foo

給定一個區塊,使用第一個子程序的 stdin 串流,以及等待程序的陣列呼叫該區塊。

Open3.pipeline_w('sort', 'cat -n') do |first_stdin, wait_threads|
  first_stdin.puts("foo\nbar\nbaz")
  first_stdin.close # Send EOF to sort.
  wait_threads.each do |wait_thread|
    wait_thread.join
  end
end

輸出

1 bar
2 baz
3 foo

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

如果第一個參數是雜湊,它會成為每個呼叫 Process.spawn 的主要參數 env;請參閱 執行環境

如果最後一個參數是雜湊,它會成為每個呼叫 Process.spawn 的尾端參數 options;請參閱 執行選項

cmds 中的每個剩餘參數為下列其中之一:

  • command_line:字串,以 shell 保留字或特殊內建函數開頭,或包含一個或多個元字元。

  • exe_path:字串路徑,指向要呼叫的可執行檔。

  • 包含 command_lineexe_path 的陣列,以及命令的零個或多個字串參數。

請參閱 參數 command_line 或 exe_path

# File lib/open3.rb, line 1195
def pipeline_w(*cmds, &block)
  if Hash === cmds.last
    opts = cmds.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  pipeline_run(cmds, opts, [in_r], [in_w], &block)
end
popen2([env, ] command_line, options = {}) → [stdin, stdout, wait_thread] 按一下以切換來源
popen2([env, ] exe_path, *args, options = {}) → [stdin, stdout, wait_thread]
popen2([env, ] command_line, options = {}) {|stdin, stdout, wait_thread| ... } → object
popen2([env, ] exe_path, *args, options = {}) {|stdin, stdout, wait_thread| ... } → object

基本上是 Process.spawn 的包裝器,它

  • 透過使用給定的引數呼叫 Process.spawn 來建立子程序。

  • 建立串流 stdinstdout,它們是子程序中的標準輸入和標準輸出串流。

  • 建立執行緒 wait_thread,等待子程序結束;該執行緒有方法 pid,它傳回子程序的程序識別碼。

如果沒有給定區塊,則傳回陣列 [stdin, stdout, wait_thread]。呼叫者應關閉兩個傳回的串流。

stdin, stdout, wait_thread = Open3.popen2('echo')
# => [#<IO:fd 6>, #<IO:fd 7>, #<Process::Waiter:0x00007f58d52dbe98 run>]
stdin.close
stdout.close
wait_thread.pid   # => 2263572
wait_thread.value # => #<Process::Status: pid 2263572 exit 0>

給定一個區塊,使用三個變數(兩個串流和等待執行緒)呼叫該區塊,並傳回區塊的傳回值。呼叫者不需要關閉串流。

Open3.popen2('echo') do |stdin, stdout, wait_thread|
  p stdin
  p stdout
  p wait_thread
  p wait_thread.pid
  p wait_thread.value
end

輸出

#<IO:fd 6>
#<IO:fd 7>
#<Process::Waiter:0x00007f58d59a34b0 sleep>
2263636
#<Process::Status: pid 2263636 exit 0>

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會在呼叫 Process.spawn 時,變成領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會在呼叫 Process.spawn 時,變成尾隨引數 options;請參閱 執行選項

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.popen2('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
Open3.popen2('echo') {|*args| p args }                         # Built-in.
Open3.popen2('date > date.tmp') {|*args| p args }              # Contains meta character.

輸出(對於上述每個呼叫都類似)

# => [#<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f7577dfe410 dead>]

命令列也可能包含命令的引數和選項

Open3.popen2('echo "Foo"') { |i, o, t| o.gets }
"Foo\n"

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.popen2('/usr/bin/date') { |i, o, t| o.gets }
# => "Thu Sep 28 09:41:06 AM CDT 2023\n"

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.popen2('doesnt_exist') { |i, o, t| o.gets } # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.popen2('echo', 'C #') { |i, o, t| o.gets }
# => "C #\n"
Open3.popen2('echo', 'hello', 'world') { |i, o, t| o.gets }
# => "hello world\n"

相關

  • Open3.popen2e:使子處理程序的標準輸入和標準輸出與標準錯誤串流的合併可用於個別串流。

  • Open3.popen3:使子處理程序的標準輸入、標準輸出和標準錯誤串流可用於個別串流。

# File lib/open3.rb, line 365
def popen2(*cmd, &block)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
end
popen2e([env, ] command_line, options = {}) → [stdin, stdout_and_stderr, wait_thread] 按一下以切換來源
popen2e([env, ] exe_path, *args, options = {}) → [stdin, stdout_and_stderr, wait_thread]
popen2e([env, ] command_line, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } → object
popen2e([env, ] exe_path, *args, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } → object

基本上是 Process.spawn 的包裝器,它

  • 透過使用給定的引數呼叫 Process.spawn 來建立子程序。

  • 建立串流 stdinstdout_and_stderr,它們是子處理程序中的標準輸入和標準輸出與標準錯誤串流的合併。

  • 建立執行緒 wait_thread,等待子程序結束;該執行緒有方法 pid,它傳回子程序的程序識別碼。

如果沒有給定區塊,則傳回陣列 [stdin, stdout_and_stderr, wait_thread]。呼叫者應關閉兩個傳回的串流。

stdin, stdout_and_stderr, wait_thread = Open3.popen2e('echo')
# => [#<IO:fd 6>, #<IO:fd 7>, #<Process::Waiter:0x00007f7577da4398 run>]
stdin.close
stdout_and_stderr.close
wait_thread.pid   # => 2274600
wait_thread.value # => #<Process::Status: pid 2274600 exit 0>

給定一個區塊,使用三個變數(兩個串流和等待執行緒)呼叫該區塊,並傳回區塊的傳回值。呼叫者不需要關閉串流。

Open3.popen2e('echo') do |stdin, stdout_and_stderr, wait_thread|
  p stdin
  p stdout_and_stderr
  p wait_thread
  p wait_thread.pid
  p wait_thread.value
end

輸出

#<IO:fd 6>
#<IO:fd 7>
#<Process::Waiter:0x00007f75777578c8 sleep>
2274763
#<Process::Status: pid 2274763 exit 0>

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會在呼叫 Process.spawn 時,變成領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會在呼叫 Process.spawn 時,變成尾隨引數 options;請參閱 執行選項

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.popen2e('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
Open3.popen2e('echo') {|*args| p args }                         # Built-in.
Open3.popen2e('date > date.tmp') {|*args| p args }              # Contains meta character.

輸出(對於上述每個呼叫都類似)

# => [#<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f7577d8a1f0 dead>]

命令列也可能包含命令的引數和選項

Open3.popen2e('echo "Foo"') { |i, o_and_e, t| o_and_e.gets }
"Foo\n"

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.popen2e('/usr/bin/date') { |i, o_and_e, t| o_and_e.gets }
# => "Thu Sep 28 01:58:45 PM CDT 2023\n"

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.popen2e('doesnt_exist') { |i, o_and_e, t| o_and_e.gets } # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.popen2e('echo', 'C #') { |i, o_and_e, t| o_and_e.gets }
# => "C #\n"
Open3.popen2e('echo', 'hello', 'world') { |i, o_and_e, t| o_and_e.gets }
# => "hello world\n"

相關

  • Open3.popen2:使子處理程序的標準輸入和標準輸出串流可用於個別串流,但無法存取標準錯誤串流。

  • Open3.popen3:使子處理程序的標準輸入、標準輸出和標準錯誤串流可用於個別串流。

# File lib/open3.rb, line 508
def popen2e(*cmd, &block)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[[:out, :err]] = out_w

  popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
ensure
  if block
    in_r.close
    in_w.close
    out_r.close
    out_w.close
  end
end
popen3([env, ] command_line, options = {}) → [stdin, stdout, stderr, wait_thread] 按一下以切換來源
popen3([env, ] exe_path, *args, options = {}) → [stdin, stdout, stderr, wait_thread]
popen3([env, ] command_line, options = {}) {|stdin, stdout, stderr, wait_thread| ... } → object
popen3([env, ] exe_path, *args, options = {}) {|stdin, stdout, stderr, wait_thread| ... } → object

基本上是 Process.spawn 的包裝器,它

  • 透過使用給定的引數呼叫 Process.spawn 來建立子程序。

  • 建立串流 stdinstdoutstderr,它們是子處理程序中的標準輸入、標準輸出和標準錯誤串流。

  • 建立執行緒 wait_thread,等待子程序結束;該執行緒有方法 pid,它傳回子程序的程序識別碼。

如果沒有給定區塊,則傳回陣列 [stdin, stdout, stderr, wait_thread]。呼叫者應關閉三個傳回的串流。

stdin, stdout, stderr, wait_thread = Open3.popen3('echo')
# => [#<IO:fd 8>, #<IO:fd 10>, #<IO:fd 12>, #<Process::Waiter:0x00007f58d5428f58 run>]
stdin.close
stdout.close
stderr.close
wait_thread.pid   # => 2210481
wait_thread.value # => #<Process::Status: pid 2210481 exit 0>

如果給定區塊,則使用四個變數(三個串流和等待執行緒)呼叫區塊,並傳回區塊的傳回值。呼叫者不需要關閉串流

Open3.popen3('echo') do |stdin, stdout, stderr, wait_thread|
  p stdin
  p stdout
  p stderr
  p wait_thread
  p wait_thread.pid
  p wait_thread.value
end

輸出

#<IO:fd 6>
#<IO:fd 7>
#<IO:fd 9>
#<Process::Waiter:0x00007f58d53606e8 sleep>
2211047
#<Process::Status: pid 2211047 exit 0>

Process.spawn 類似,如果使用不受信任的輸入呼叫此方法,可能會產生安全漏洞;請參閱 命令注入

Process.spawn 不同,此方法會等到子處理程序結束後才傳回,因此呼叫端不需要執行此動作。

如果第一個引數是雜湊,它會在呼叫 Process.spawn 時,變成領先引數 env;請參閱 執行環境

如果最後一個引數是雜湊,它會在呼叫 Process.spawn 時,變成尾隨引數 options;請參閱 執行選項

單一必需引數為下列其中之一

  • command_line 如果它是一個字串,且它以 shell 保留字或特殊內建函數開頭,或如果它包含一個或多個元字元。

  • exe_path 否則。

引數 command_line

字串引數 command_line 是要傳遞給 shell 的命令列;它必須以 shell 保留字開頭,以特殊內建函數開頭,或包含元字元

Open3.popen3('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
Open3.popen3('echo') {|*args| p args }                         # Built-in.
Open3.popen3('date > date.tmp') {|*args| p args }              # Contains meta character.

輸出(對於上述每個呼叫都類似)

[#<IO:(closed)>, #<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f58d52f28c8 dead>]

命令列也可能包含命令的引數和選項

Open3.popen3('echo "Foo"') { |i, o, e, t| o.gets }
"Foo\n"

引數 exe_path

引數 exe_path 是下列其中之一

  • 要呼叫的可執行檔的字串路徑。

  • 包含可執行檔路徑和用作執行處理程序名稱的字串的 2 元素陣列。

範例

Open3.popen3('/usr/bin/date') { |i, o, e, t| o.gets }
# => "Wed Sep 27 02:56:44 PM CDT 2023\n"

Ruby 直接呼叫可執行檔,沒有 shell 和沒有 shell 展開

Open3.popen3('doesnt_exist') { |i, o, e, t| o.gets } # Raises Errno::ENOENT

如果給定一個或多個 args,每個都是要傳遞給可執行檔的引數或選項

Open3.popen3('echo', 'C #') { |i, o, e, t| o.gets }
# => "C #\n"
Open3.popen3('echo', 'hello', 'world') { |i, o, e, t| o.gets }
# => "hello world\n"

小心避免死結。輸出串流 stdoutstderr 有固定大小的緩衝區,所以大量讀取其中一個但未讀取另一個,當未讀取的緩衝區填滿時可能會造成死結。為避免這種情況,stdoutstderr 應同時讀取(使用執行緒或 IO.select)。

相關

  • Open3.popen2:使子處理程序的標準輸入和標準輸出串流可用於個別串流,但無法存取標準錯誤串流。

  • Open3.popen2e:使子處理程序的標準輸入和標準輸出與標準錯誤串流的合併可用於個別串流。

# File lib/open3.rb, line 218
def popen3(*cmd, &block)
  if Hash === cmd.last
    opts = cmd.pop.dup
  else
    opts = {}
  end

  in_r, in_w = IO.pipe
  opts[:in] = in_r
  in_w.sync = true

  out_r, out_w = IO.pipe
  opts[:out] = out_w

  err_r, err_w = IO.pipe
  opts[:err] = err_w

  popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block)
end