Код виходу перевірити команду рубінової системи


106

У мене є безліч системних дзвінків в рубіні, таких як наведені нижче, і я хочу перевірити їхні вихідні коди одночасно, щоб мій скрипт вийшов, якщо ця команда не вдалася.

system("VBoxManage createvm --name test1")
system("ruby test.rb")

Я хочу щось подібне

system("VBoxManage createvm --name test1", 0) <- де другий параметр перевіряє код виходу та підтверджує, що цей системний виклик був успішним, а якщо ні, він викличе помилку або зробить щось подібне.

Це взагалі можливо?

Я щось спробував у цьому, і це теж не вийшло.

system("ruby test.rb")
system("echo $?")

або

`ruby test.rb`
exit_code = `echo $?`
if exit_code != 0
  raise 'Exit code is not zero'
end


У наведеному вище прикладі exit_codeбуде рядок - або "0\n"або "1\n", так exit_code != 0завжди буде правдою
dgmstuart

Відповіді:


166

З документації :

система повертається, trueякщо команда дає нульовий статус виходу, falseдля ненульового стану виходу. Повертається, nilякщо виконання команди не вдалося.

system("unknown command")     #=> nil
system("echo foo")            #=> true
system("echo foo | grep bar") #=> false

Крім того

Статус помилки доступний у $?.

system("VBoxManage createvm --invalid-option")

$?             #=> #<Process::Status: pid 9926 exit 2>
$?.exitstatus  #=> 2

2
і як захопити його вихід (не код виходу) до змінної?
ア レ ッ ク ス

Якщо ви знаходитесь в консолі рейки, випробовуючи це, просто пам’ятайте, що ви можете втратити значення $? тому вам потрібно захопити його як частину команди [10] pry(main)> system("touch /root/test 2> /dev/null") => false [11] pry(main)> $?.exitstatus => 0 [12] pry(main)> system("touch /root/test 2> /dev/null"); $?.exitstatus => 1
REPL

Ще одне відмінне порівняння system, зворотній зв'язок %xта execнадане тут: stackoverflow.com/questions/6338908/…
Том Гаррісон,

38

Для мене я вважаю за краще використовувати `` для виклику команд оболонки та перевірки $? щоб отримати статус процесу. $? є об'єктом статусу процесу, ви можете отримати інформацію про процес команди від цього об'єкта, включаючи: код статусу, стан виконання, pid тощо.

Деякі корисні методи $? об’єкт:

   $?.exitstatus => return error code    
   $?.success? => return true if error code is 0, otherwise false
   $?.pid => created process pid

1
За допомогою Rubocop я з'ясував, що читаним псевдонімом $?є$CHILD_STATUS
RajaRaviVarma

26

systemповертається, falseякщо в команді є ненульовий код виходу, або nilякщо немає команди.

Тому

system( "foo" ) or exit

або

system( "foo" ) or raise "Something went wrong with foo"

повинні працювати і бути досить стислими.


6

Ви не фіксуєте результат свого systemдзвінка, і саме тут повертається код результату:

exit_code = system("ruby test.rb")

Запам’ятайте кожен systemвиклик або еквівалент, який включає метод backtick, породжує нову оболонку, тому неможливо зафіксувати результат середовища попередньої оболонки. У цьому випадку exit_code, trueякщо все склалося, nilінакше.

popen3Команда забезпечує більш низький рівень деталізації.


2
Open3.capture3є особливо простим методом використання для подібного роду завдань.
Олов'яний чоловік

6

Один із способів зробити це - це зв'язати їх за допомогою andабо &&:

system("VBoxManage createvm --name test1") and system("ruby test.rb")

Другий виклик не буде запущений, якщо перший не вдався.

Ви можете обернути їх у вікно, if ()щоб отримати деякий контроль потоку:

if (
  system("VBoxManage createvm --name test1") && 
  system("ruby test.rb")
) 
  # do something
else
  # do something with $?
end

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