Ruby, разница между exec, system и% x () или обратными ссылками

370

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

exec, systemИ %x()или Обратные кавычки

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

Мистер Блэк
источник
1
Эти и многие другие команды достаточно хорошо объяснены в документах: обратные
ссылки
1
На эту тему есть отличная статья на тему Ruby Quicktips: выполнение команд оболочки .
Симон Перепелица
6
Так как кто-то только что откопал эту старую ветку, «Работа с процессами Unix» - отличная книга для Rubyists, интересующихся этой темой: workingwithunixprocesses.com
Michael Kohl
1
Я удивлен, что ни один из ответов не упоминает sh.
Деннис
@Dennis Когда я поднимал этот вопрос, ruby ​​1.9.3 * не был выпущен.
Мистер Блэк,

Ответы:

411

система

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>

Обратные кавычки

Обратные знаки (``) вызывают системную программу и возвращают ее вывод. В отличие от первого подхода, команда предоставляется не через строку, а путем помещения ее в пару обратных символов.

>> `date`
=> Wed Sep 4 22:22:51 CEST 2013   

Глобальная переменная также $?устанавливается с помощью обратных кавычек. С помощью обратных галочек вы также можете использовать интерполяцию строк.

%Икс()

Использование %xявляется альтернативой стилю backticks. Он также вернет вывод. Как и его родственники %wи %q(среди прочего), любой разделитель будет достаточным, если разделители в стиле скобок совпадают. Это значит %x(date), %x{date}и %x-date-все это синонимы. Как и обратные пометки, %xможно использовать интерполяцию строк.

Exec

При использовании Kernel#execтекущего процесса (ваш скрипт на Ruby) он заменяется процессом, вызванным через 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
И для более мелкозернистого контроля , как ручки вызова STDIN, STDOUT, STDERR, рассмотреть Open3.popen3вместо; например, см. stackoverflow.com/a/10922097/258662
cboettig
1
Спасибо, что упомянули, что обратные галочки поддерживают интерполяцию строк, что решило мою проблему.
ADG
244

Вот блок-схема, основанная на этом ответе . Смотрите также, используя scriptдля эмуляции терминала .

введите описание изображения здесь

Ян
источник
3
Это не так просто. В моем случае было «нормально (и нужно) блокировать до завершения процесса», чтобы затем использовать popen3 для проверки выходов STDOUT / STDERR.
Накилон
Вы всегда можете вызвать неблокирующий вызов (эффективно) блока, заключив его в цикл while. Вы не можете легко сделать блокирующий вызов неблокирующим.
Ян
106

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

Уильям Перселл
источник