Ruby, Разница между exec, system и% x() или Backticks

В чем разница между следующими методами Ruby?

exec, system и %x() или Backticks

Я знаю, что они используются для выполнения команд терминала программно через Ruby, но я хотел бы знать, почему существует три разных способа сделать это.

Ответ 1

система

Метод 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

Ответ 3

Они делают разные вещи. exec заменяет текущий процесс новым процессом и никогда не возвращает. system вызывает другой процесс, а возвращает свое значение выхода в текущий процесс. Использование backticks вызывает другой процесс и возвращает выход этого процесса в текущий процесс.