модуль Open3
Модуль Open3 поддерживает создание дочерних процессов с доступом к потокам $stdin, $stdout и $stderr.
Что здесь
Каждый из этих методов выполняет заданную команду в новом процессе или подоболочке, или несколько команд в новых процессах и/или подоболочках:
-
Каждый из этих методов выполняет одну команду в процессе или подоболочке, принимает строку для ввода в $stdin и возвращает строку вывода из $stdout, $stderr или обоих:
-
Open3.capture2: Выполняет команду; возвращает строку из $stdout. -
Open3.capture2e: Выполняет команду; возвращает строку из объединённых $stdout и $stderr. -
Open3.capture3: Выполняет команду; возвращает строки из $stdout и $stderr.
-
-
Каждый из этих методов выполняет одну команду в процессе или подоболочке и возвращает каналы для $stdin, $stdout и/или $stderr:
-
Open3.popen2: Выполняет команду; возвращает каналы для $stdin и $stdout. -
Open3.popen2e: Выполняет команду; возвращает каналы для $stdin и объединённых $stdout и $stderr. -
Open3.popen3: Выполняет команду; возвращает каналы для $stdin, $stdout и $stderr.
-
-
Каждый из этих методов выполняет одну или несколько команд в процессах и/или подоболочках, возвращает каналы для первого $stdin, последнего $stdout или обоих:
-
Open3.pipeline_r: Возвращает канал для последнего $stdout. -
Open3.pipeline_rw: Возвращает каналы для первого $stdin и последнего $stdout. -
Open3.pipeline_w: Возвращает канал для первого $stdin. -
Open3.pipeline_start: Не ожидает завершения процессов. -
Open3.pipeline: Ожидает завершения процессов.
-
Каждый из вышеперечисленных методов принимает:
-
Необязательный хеш с именами и значениями переменных среды; см. Окружение выполнения.
-
Обязательный строковый аргумент, являющийся
command_lineилиexe_path; см. Аргумент command_line или exe_path. -
Необязательный хеш с параметрами выполнения; см. Параметры выполнения.
Константы
- VERSION
Публичные методы класса
Исходный код
# 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 В основном, обёртка для Open3.popen3, которая:
-
Создаёт дочерний процесс, вызывая
Open3.popen3с заданными аргументами (кроме определённых записей в хешеoptions; см. ниже). -
Возвращает как строку
stdout_sстандартный вывод дочернего процесса. -
Возвращает как
statusобъектProcess::Status, который представляет собой код завершения дочернего процесса.
Возвращает массив [stdout_s, status]:
stdout_s, status = Open3.capture2('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326047 exit 0>]
Как и Process.spawn, этот метод имеет потенциальные уязвимости в безопасности, если вызван с недоверенным вводом; см. Инъекция команды.
В отличие от Process.spawn, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающему методу не нужно этого делать.
Если первый аргумент является хешем, он становится ведущим аргументом env в вызове Open3.popen3; см. Окружение выполнения.
Если последний аргумент является хешем, он становится завершающим аргументом options в вызове Open3.popen3; см. Параметры выполнения.
Хеш options задан; два параметра имеют локальное влияние в методе Open3.capture2:
-
Если запись
options[:stdin_data]существует, запись удаляется, и её строковое значение отправляется на стандартный ввод команды:Open3.capture2('tee', stdin_data: 'Foo') # => ["Foo", #<Process::Status: pid 2326087 exit 0>] -
Если запись
options[:binmode]существует, запись удаляется, и внутренние потоки устанавливаются в двоичный режим.
Единственный обязательный аргумент — это одно из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специальной встроенной команды, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая будет передана оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специальной встроенной команды или содержать метасимволы:
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 вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 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 В основном, обёртка для Open3.popen3, которая:
-
Создаёт дочерний процесс, вызывая
Open3.popen3с заданными аргументами (кроме определённых записей в хешеoptions; см. ниже). -
Возвращает как строку
stdout_and_stderr_sобъединённый стандартный вывод и стандартную ошибку дочернего процесса. -
Возвращает как
statusобъектProcess::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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающему методу не нужно этого делать.
Если первый аргумент является хешем, он становится ведущим аргументом env в вызове Open3.popen3; см. Окружение выполнения.
Если последний аргумент является хешем, он становится завершающим аргументом options в вызове Open3.popen3; см. Параметры выполнения.
Хеш options задан; два параметра имеют локальное влияние в методе Open3.capture2e:
-
Если запись
options[:stdin_data]существует, запись удаляется, и её строковое значение отправляется на стандартный ввод команды:Open3.capture2e('tee', stdin_data: 'Foo') # => ["Foo", #<Process::Status: pid 2371732 exit 0>] -
Если запись
options[:binmode]существует, запись удаляется, и внутренние потоки устанавливаются в двоичный режим.
Единственный обязательный аргумент — это одно из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специальной встроенной команды, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая будет передана оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специальной встроенной команды или содержать метасимволы:
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 вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 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 В основном это обёртка для Open3.popen3, которая:
-
Создаёт дочерний процесс, вызывая
Open3.popen3с заданными аргументами (за исключением определённых элементов в хешеoptions; см. ниже). -
Возвращает в виде строк
stdout_sиstderr_sстандартный вывод и стандартную ошибку дочернего процесса. -
Возвращает в виде
statusобъектProcess::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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающей стороне не нужно этого делать.
Если первый аргумент является хешем, он становится ведущим аргументом env при вызове Open3.popen3; см. Окружение выполнения.
Если последний аргумент является хешем, он становится заключительным аргументом options при вызове Open3.popen3; см. Параметры выполнения.
Хеш options задаётся; два параметра действуют локально в методе Open3.capture3:
-
Если существует элемент
options[:stdin_data], элемент удаляется, а его строковое значение отправляется в стандартный ввод команды:Open3.capture3('tee', stdin_data: 'Foo') # => ["Foo", "", #<Process::Status: pid 2319575 exit 0>] -
Если существует элемент
options[:binmode], элемент удаляется, а внутренние потоки устанавливаются в двоичный режим.
Единственный обязательный аргумент — это одно из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая передаётся оболочке; она должна начинаться с зарезервированного слова оболочки, с специального встроенного или содержать метасимволы:
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 вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 1334
def pipeline(*cmds)
if Hash === cmds.last
opts = cmds.pop.dup
else
opts = {}
end
pipeline_run(cmds, opts, [], []) {|ts|
ts.map(&:value)
}
end В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmdsвызываяProcess.spawn. -
Направляет
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, этот метод может иметь потенциальные уязвимости в случае использования небезопасных данных в качестве входных данных; см. Инъекция команд.
Если первый аргумент является хешем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент является хешем, он становится заключительным аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый оставшийся аргумент в cmds представляет собой:
-
Командную строку: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного, или содержащая один или несколько метасимволов.
-
Путь к исполняемому файлу: строковый путь к исполняемому файлу, который необходимо вызвать.
-
Массив, содержащий командную строку или путь к исполняемому файлу, а также нулевые или более строковых аргументов для команды.
Исходный код
# 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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmdsвызываяProcess.spawn. -
Направляет
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, этот метод может иметь потенциальные уязвимости в случае использования небезопасных данных в качестве входных данных; см. Инъекция команд.
Если первый аргумент является хешем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент является хешем, он становится заключительным аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый оставшийся аргумент в cmds представляет собой:
-
Командную строку: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного, или содержащая один или несколько метасимволов.
-
Путь к исполняемому файлу: строковый путь к исполняемому файлу, который необходимо вызвать.
-
Массив, содержащий командную строку или путь к исполняемому файлу, а также нулевые или более строковых аргументов для команды.
Исходный код
# 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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из переданных
cmdsвызываяProcess.spawn. -
Перенаправляет
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, этот метод может иметь потенциальные уязвимости в области безопасности, если вызван с недоверенными данными; см. Внедрение команд.
Если первый аргумент является хэшем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Выполняемая среда.
Если последний аргумент является хэшем, он становится хвостовым аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый оставшийся аргумент в cmds является одним из:
-
command_line: строка, начинающаяся со служебного слова оболочки или специального встроенного, или содержащая один или несколько метасимволов. -
exe_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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из переданных
cmdsвызываяProcess.spawn. -
Не ожидает завершения дочерних процессов.
Без блока возвращает массив потоков ожидания для всех дочерних процессов.
Пример:
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, этот метод может иметь потенциальные уязвимости в области безопасности, если вызван с недоверенными данными; см. Внедрение команд.
Если первый аргумент является хэшем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Выполняемая среда.
Если последний аргумент является хэшем, он становится хвостовым аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый оставшийся аргумент в cmds является одним из:
-
command_line: строка, начинающаяся со служебного слова оболочки или специального встроенного, или содержащая один или несколько метасимволов. -
exe_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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из переданных
cmdsвызываяProcess.spawn. -
Перенаправляет
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, этот метод может иметь потенциальные уязвимости в области безопасности, если вызван с недоверенными данными; см. Внедрение команд.
Если первый аргумент является хэшем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Выполняемая среда.
Если последний аргумент является хэшем, он становится хвостовым аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый оставшийся аргумент в cmds является одним из:
-
command_line: строка, начинающаяся со служебного слова оболочки или специального встроенного, или содержащая один или несколько метасимволов. -
exe_path: строковый путь к исполняемому файлу, который должен быть вызван. -
Массив, содержащий
command_lineилиexe_path, а также ноль или более строковых аргументов для команды.
Исходный код
# 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 В основном, обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс, вызывая
Process.spawnс указанными аргументами. -
Создаёт потоки
stdinиstdout, которые представляют собой стандартный ввод и стандартный вывод в дочернем процессе. -
Создаёт поток
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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающему коду не нужно этого делать.
Если первый аргумент — хэш, он становится ведущим аргументом env в вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент — хэш, он становится хвостовым аргументом options в вызове Process.spawn; см. Параметры выполнения.
Единственный обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с ключевого слова оболочки или специального встроенного или содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, передаваемая в оболочку; она должна начинаться с ключевого слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 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 В основном, обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс, вызывая
Process.spawnс указанными аргументами. -
Создаёт потоки
stdin,stdout_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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающему коду не нужно этого делать.
Исходный код
# 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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс, вызывая
Process.spawnс заданными аргументами. -
Создаёт потоки
stdin,stdout, иstderr, которые являются стандартными потоками ввода, вывода и ошибок дочернего процесса. -
Создаёт поток
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, этот метод ждёт завершения дочернего процесса перед возвратом, поэтому вызывающий код не должен этого делать.
Если первый аргумент — хеш, он становится ведущим аргументом env при вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент — хеш, он становится заключительным аргументом options при вызове Process.spawn; см. Параметры выполнения.
Единственный обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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"
Следите за предотвращением тупиков. Потоки вывода stdout и stderr имеют буферы фиксированного размера, поэтому извлечение данных из одного из них в большом объёме, но не из другого, может привести к тупику, когда заполнится необработанный буфер. Чтобы избежать этого, stdout и stderr должны считываться одновременно (с использованием потоков или IO.select).
Связанные:
-
Open3.popen2: Делает стандартные потоки ввода и вывода дочернего процесса доступными как отдельные потоки без доступа к стандартному потоку ошибок. -
Open3.popen2e: Делает стандартный поток ввода и объединённые стандартные потоки вывода и ошибок дочернего процесса доступными как отдельные потоки.
Методы частного экземпляра
Исходный код
# 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 В основном это обёртка для Open3.popen3, которая:
-
Создаёт дочерний процесс, вызывая
Open3.popen3с заданными аргументами (за исключением определённых элементов в хэшеoptions; см. ниже). -
Возвращает строковое представление стандартного вывода дочернего процесса.
-
Возвращает объект
Process::Status, представляющий код завершения дочернего процесса.
Возвращает массив [stdout_s, status]:
stdout_s, status = Open3.capture2('echo "Foo"')
# => ["Foo\n", #<Process::Status: pid 2326047 exit 0>]
Как и метод Process.spawn, этот метод может иметь уязвимости в области безопасности, если вызывается с недоверенными данными; см. Ввод команд.
В отличие от Process.spawn, этот метод ждёт завершения дочернего процесса перед возвратом, поэтому вызывающей стороне не нужно это делать.
Если первый аргумент является хэшем, он становится ведущим аргументом env в вызове Open3.popen3; см. Выполнение среды.
Если последний аргумент является хэшем, он становится заключительным аргументом options в вызове Open3.popen3; см. Параметры выполнения.
Указан хэш options; два параметра действуют локально в методе Open3.capture2:
-
Если существует элемент
options[:stdin_data], он удаляется, и его строковое значение отправляется в стандартный ввод команды:Open3.capture2('tee', stdin_data: 'Foo') # => ["Foo", #<Process::Status: pid 2326087 exit 0>] -
Если существует элемент
options[:binmode], он удаляется, и внутренние потоки устанавливаются в двоичный режим.
Единственный обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая должна быть передана оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 может быть одним из следующих:
-
Путь к исполняемому файлу, который нужно вызвать.
-
Массив из двух элементов, содержащий путь к исполняемому файлу и строку, используемую в качестве имени выполняемого процесса.
Пример:
Open3.capture2('/usr/bin/date')
# => ["Fri Sep 29 01:00:39 PM CDT 2023\n", #<Process::Status: pid 2326222 exit 0>]
Ruby вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 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 В основном это обёртка для Open3.popen3, которая:
-
Создаёт дочерний процесс, вызывая
Open3.popen3с заданными аргументами (за исключением определённых элементов в хэшеoptions; см. ниже). -
Возвращает строковое представление объединённого стандартного вывода и стандартной ошибки дочернего процесса.
-
Возвращает объект
Process::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, этот метод ждёт завершения дочернего процесса перед возвратом, поэтому вызывающей стороне не нужно это делать.
Если первый аргумент является хэшем, он становится ведущим аргументом env в вызове Open3.popen3; см. Выполнение среды.
Если последний аргумент является хэшем, он становится заключительным аргументом options в вызове Open3.popen3; см. Параметры выполнения.
Указан хэш options; два параметра действуют локально в методе Open3.capture2e:
-
Если существует элемент
options[:stdin_data], он удаляется, и его строковое значение отправляется в стандартный ввод команды:Open3.capture2e('tee', stdin_data: 'Foo') # => ["Foo", #<Process::Status: pid 2371732 exit 0>] -
Если существует элемент
options[:binmode], он удаляется, и внутренние потоки устанавливаются в двоичный режим.
Единственный обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая должна быть передана оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 может быть одним из следующих:
-
Путь к исполняемому файлу, который нужно вызвать.
-
Массив из двух элементов, содержащий путь к исполняемому файлу и строку, используемую в качестве имени выполняемого процесса.
Пример:
Open3.capture2e('/usr/bin/date')
# => ["Sat Sep 30 09:01:46 AM CDT 2023\n", #<Process::Status: pid 2371820 exit 0>]
Ruby вызывает исполняемый файл напрямую, без оболочки и без расширения оболочки:
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 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 В основном, это обёртка для Open3.popen3, которая:
-
Создаёт дочерний процесс, вызывая
Open3.popen3с заданными аргументами (кроме некоторых элементов в хэшеoptions; см. ниже). -
Возвращает в виде строк
stdout_sиstderr_sстандартный вывод и стандартную ошибку дочернего процесса. -
Возвращает в виде
statusобъектProcess::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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающей стороне не нужно этого делать.
Если первый аргумент является хэшем, он становится ведущим аргументом env в вызове Open3.popen3; см. Окружение выполнения.
Если последний аргумент является хэшем, он становится конечным аргументом options в вызове Open3.popen3; см. Опции выполнения.
Хэш options задан; две опции действуют локально в методе Open3.capture3:
-
Если существует запись
options[:stdin_data], запись удаляется, а её строковое значение отправляется на стандартный ввод команды:Open3.capture3('tee', stdin_data: 'Foo') # => ["Foo", "", #<Process::Status: pid 2319575 exit 0>] -
Если существует запись
options[:binmode], запись удаляется, и внутренние потоки устанавливаются в двоичный режим.
Единственный необходимый аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного элемента, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, которая передаётся оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного элемента или содержать метасимволы:
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 вызывает исполняемый файл напрямую без оболочки и без расширения оболочки:
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 1334
def pipeline(*cmds)
if Hash === cmds.last
opts = cmds.pop.dup
else
opts = {}
end
pipeline_run(cmds, opts, [], []) {|ts|
ts.map(&:value)
}
end В основном, это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmds, вызываяProcess.spawn. -
Направляет
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, этот метод потенциально уязвим к атакам с использованием ненадёжных входных данных; см. Инъекция команд.
Если первый аргумент является хэшем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент является хэшем, он становится конечным аргументом options в каждом вызове Process.spawn; см. Опции выполнения.
Каждый оставшийся аргумент в cmds — это один из следующих:
-
command_line: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного элемента, или содержащая один или несколько метасимволов. -
exe_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 В основном, это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmds, вызываяProcess.spawn. -
Направляет
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, этот метод потенциально уязвим к атакам с использованием ненадёжных входных данных; см. Инъекция команд.
Если первый аргумент является хэшем, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент является хэшем, он становится конечным аргументом options в каждом вызове Process.spawn; см. Опции выполнения.
Каждый оставшийся аргумент в cmds — это один из следующих:
-
command_line: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного элемента, или содержащая один или несколько метасимволов. -
exe_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 В основном, это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmdsс помощью вызоваProcess.spawn. -
Перенаправляет
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, этот метод имеет потенциальные уязвимости в области безопасности, если вызывается с недоверенным вводом; см. Ввод команд.
Если первый аргумент — хеш, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент — хеш, он становится заключительным аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый последующий аргумент в cmds является одним из следующих:
-
command_line: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного слова, или содержащая один или несколько метасимволов. -
exe_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 В основном, это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmdsс помощью вызоваProcess.spawn. -
Не ждёт завершения дочерних процессов.
Без блока возвращает массив потоков ожидания для всех дочерних процессов.
Пример:
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, этот метод имеет потенциальные уязвимости в области безопасности, если вызывается с недоверенным вводом; см. Ввод команд.
Если первый аргумент — хеш, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент — хеш, он становится заключительным аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый последующий аргумент в cmds является одним из следующих:
-
command_line: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного слова, или содержащая один или несколько метасимволов. -
exe_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 В основном, это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс для каждого из заданных
cmdsс помощью вызоваProcess.spawn. -
Перенаправляет
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, этот метод имеет потенциальные уязвимости в области безопасности, если вызывается с недоверенным вводом; см. Ввод команд.
Если первый аргумент — хеш, он становится ведущим аргументом env в каждом вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент — хеш, он становится заключительным аргументом options в каждом вызове Process.spawn; см. Параметры выполнения.
Каждый последующий аргумент в cmds является одним из следующих:
-
command_line: строка, начинающаяся с зарезервированного слова оболочки или специального встроенного слова, или содержащая один или несколько метасимволов. -
exe_path: строковой путь к исполняемому файлу, который нужно вызвать. -
Массив, содержащий
command_lineилиexe_path, а также ноль или более строковых аргументов для команды.
Исходный код
# 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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс, вызывая
Process.spawnс заданными аргументами. -
Создаёт потоки
stdinиstdout, которые представляют стандартные входные и выходные потоки в дочернем процессе. -
Создаёт поток
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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающий код не должен этого делать.
Если первый аргумент — хеш, он становится ведущим аргументом env в вызове Process.spawn; см. Выполняющая среда.
Если последний аргумент — хеш, он становится последующим аргументом options в вызове Process.spawn; см. Параметры выполнения.
Единственный обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 вызывает исполняемый файл непосредственно, без оболочки и без расширения оболочки:
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 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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс, вызывая
Process.spawnс заданными аргументами. -
Создаёт потоки
stdin,stdout_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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающему коду не нужно этого делать.
Если первый аргумент — хеш, он становится ведущим аргументом env в вызове Process.spawn; см. Выполняющая среда.
Если последний аргумент — хеш, он становится последующим аргументом options в вызове Process.spawn; см. Параметры выполнения.
Единственный обязательный аргумент — один из следующих:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 вызывает исполняемый файл непосредственно, без оболочки и без расширения оболочки:
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 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 В основном это обёртка для Process.spawn, которая:
-
Создаёт дочерний процесс, вызывая
Process.spawnс указанными аргументами. -
Создаёт потоки
stdin,stdout, иstderr, которые являются стандартными потоками ввода, вывода и ошибок дочернего процесса. -
Создаёт поток
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, этот метод ожидает завершения дочернего процесса перед возвратом, поэтому вызывающей стороне нет необходимости делать это самостоятельно.
Если первый аргумент является хэш-таблицей, то она становится ведущим аргументом env в вызове Process.spawn; см. Окружение выполнения.
Если последний аргумент является хэш-таблицей, то она становится заключительным аргументом options в вызове Process.spawn; см. Параметры выполнения.
Единственный обязательный аргумент — это одно из следующего:
-
command_lineесли это строка, и если она начинается с зарезервированного слова оболочки или специального встроенного, или если она содержит один или несколько метасимволов. -
exe_pathв противном случае.
Аргумент command_line
Строковый аргумент command_line — это командная строка, передаваемая оболочке; она должна начинаться с зарезервированного слова оболочки, начинаться со специального встроенного или содержать метасимволы:
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 — это одно из следующего:
-
Путь к исполняемому файлу.
-
Массив из двух элементов, содержащий путь к исполняемому файлу и строку, используемую в качестве имени выполняемого процесса.
Пример:
Open3.popen3('/usr/bin/date') { |i, o, e, t| o.gets }
# => "Wed Sep 27 02:56:44 PM CDT 2023\n"
Ruby вызывает исполняемый файл непосредственно, без оболочки и без расширения оболочки:
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"
Следите за предотвращением тупиков. Потоки вывода stdout и stderr имеют буферы с фиксированным размером, поэтому чрезмерное чтение из одного потока, но не из другого, может привести к тупику, когда заполнится непрочитанный буфер. Чтобы избежать этого, stdout и stderr должны читаться одновременно (с использованием потоков или IO.select).
Связанные:
-
Open3.popen2: Делает стандартные потоки ввода и вывода дочернего процесса доступными как отдельные потоки, без доступа к потоку стандартной ошибки. -
Open3.popen2e: Делает стандартные потоки ввода и объединённый поток стандартного вывода и стандартной ошибки дочернего процесса доступными как отдельные потоки.
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.