Ruby, різниця між exec, системою та% x () або Backticks


370

Яка різниця між наступними методами Ruby?

exec, systemІ %x()чи Зворотні лапки

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


1
Ці команди, і багато інших, пояснюються дуже добре в документації: EXEC системи лапки
вишукування

1
На цю тему є чудова стаття Ruby Quicktips: Виконання команд оболонки .
Саймон Перепелиця

6
Оскільки хтось щойно перекопав цю стару нитку, "Робота з процесами Unix" - відмінна книга для рубістів, зацікавлених у темі: workingwithunixprocess.com
Майкл Коль

1
Я здивований, що жодна з відповідей не згадує sh.
Денніс

@Dennis Коли я піднімав це питання, рубін 1.9.3 * не вийшов.
Містер Блек

Відповіді:


411

система

systemМетод викликає системну програму. Ви повинні надати команду як аргумент рядка для цього методу. Наприклад:

>> system("date")
Wed Sep 4 22:03:44 CEST 2013
=> true

Викликана програма буде використовувати струм STDIN, STDOUTі STDERRоб'єкти вашої програми Ruby. Насправді, фактичне значення, що повертається або true, falseабо nil. У прикладі дата була надрукована через об'єкт IO 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 ()

Використання %xє альтернативою стилю заднього плану. Він також поверне вихід. Як і його родичі %wта %q(серед інших), будь-якого роздільника буде достатньо, доки збігаються обмежувачі у стилі дужок. Це означає %x(date), %x{date}і %x-date-всі вони є синонімами. Як і в основі зворотних посилань, %xможна використовувати стропову інтерполяцію.

виконувати

За допомогою 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
Дякую вам за те, що ви згадали, що backticks підтримує рядкову інтерполяцію, яка вирішила мою проблему.
adg

244

Ось схема, заснована на цій відповіді . Дивіться також використання scriptемуляції терміналу .

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


3
Це не так просто. У моєму випадку "було добре (і потрібно) блокувати, поки процес не завершиться", а потім використовувати popen3 для перевірки STDOUT / STDERR виходів.
Накілон

Ви завжди можете викликати незахисний виклик (ефективно) блокувати, загорнувши його в певний час. Ви не можете настільки легко здійснити блокуючий дзвінок у незаблокувальний виклик.
Ян

106

Вони роблять різні речі. execзамінює поточний процес новим і ніколи не повертається . systemвикликає інший процес і повертає його вихідне значення поточному процесу. За допомогою зворотних посилань викликає інший процес і повертає результат цього процесу в поточний процес.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.