В чем разница между следующими методами Ruby?
exec
, system
и %x()
или Backticks
Я знаю, что они используются для выполнения команд терминала программно через Ruby, но я хотел бы знать, почему существует три разных способа сделать это.
В чем разница между следующими методами Ruby?
exec
, system
и %x()
или Backticks
Я знаю, что они используются для выполнения команд терминала программно через Ruby, но я хотел бы знать, почему существует три разных способа сделать это.
система
Метод system
вызывает системную программу. Вы должны предоставить команду в качестве строкового аргумента этому методу. Например:
>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true
Вызываемая программа будет использовать текущие объекты STDIN
, STDOUT
и STDERR
вашей программы Ruby. Фактически, фактическое возвращаемое значение равно либо true
, false
или nil
. В примере дата была напечатана через объект ввода-вывода STDIN
. Метод вернет true
, если процесс завершился с нулевым статусом, false
, если процесс завершился с ненулевым статусом и nil
, если выполнение завершилось с ошибкой.
Другим побочным эффектом является то, что глобальная переменная $?
устанавливается на объект Process::Status
. Этот объект будет содержать информацию о самом вызове, включая идентификатор процесса (PID) вызываемого процесса и статус выхода.
>> system("date")
Wed Sep 4 22:11:02 CEST 2013
=> true
>> $?
=> #<Process::Status: pid 15470 exit 0>
Обратные кавычки
Backticks (` `) вызовите системную программу и верните ее вывод. В отличие от первого подхода, команда не предоставляется через строку, а путем размещения ее внутри пары обратных циклов.
>> `date`
=> Wed Sep 4 22:22:51 CEST 2013
Глобальная переменная $?
также устанавливается через обратные выходы. С backticks вы также можете использовать интерполяцию строк.
% х()
Использование %x
является альтернативой стилю backticks. Он также вернет результат. Как и его родственники %w
и %q
(среди прочих), любой разделитель будет достаточным, если совпадают разделители в стиле скобок. Это означает, что %x(date)
, %x{date}
и %x-date-
- все синонимы. Как backticks %x
может использовать интерполяцию строк.
Exec
Используя Kernel#exec
, текущий процесс (ваш Ruby script) заменяется процессом, вызванным через exec
. Метод может принимать строку в качестве аргумента. В этом случае строка будет подвержена расширению оболочки. При использовании нескольких аргументов первый используется для выполнения программы, а в качестве аргументов для вызываемой программы - следующие.
Open3.popen3
Иногда требуемая информация записывается на стандартный ввод или стандартную ошибку, и вам также необходимо получить контроль над ними. Здесь Open3.popen3
пригодится:
require 'open3'
Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread|
pid = thread.pid
puts stdout.read.chomp
end
Вот блок-схема, основанная на этом ответе. См. Также с помощью script
для эмуляции терминала.
Они делают разные вещи. exec
заменяет текущий процесс новым процессом и никогда не возвращает. system
вызывает другой процесс, а возвращает свое значение выхода в текущий процесс. Использование backticks вызывает другой процесс и возвращает выход этого процесса в текущий процесс.