2015-06-19 11 views
6

W skrypcie Ruby istnieją various ways wywołać komendy systemu/linii poleceniaJak przywrócić działanie skryptu Ruby, gdy komenda łuskanego powraca z niezerowym kodem wyjścia?

  1. backticks: `command arg1 arg2`
  2. formularza jest ograniczona, na przykład %x(command arg1 arg2) (inne ograniczniki dostępnych)
  3. Kernel#system metoda: system('command arg1 arg2')
  4. Kernel#exec metoda: exec('command arg1 arg2')

Jeśli chcę skrypt Ruby na niepowodzenie (z wyjątkiem), gdy nazywa polecenia nie powiedzie się (o niezerowej kod wyjścia) mogę też sprawdzić kod wyjścia w specjalnej zmiennej $? dla pierwszych dwóch wariantach:

`command arg1 arg2` 
fail unless $? == 0 

lub

%x,command arg1 arg2, 
fail unless $? == 0 

Jeśli jestem dobrze ze standardowym wyjściem komenda będzie standardowe wyjście skryptu Ruby (i jestem), można użyć Wariant 3 i sprawdzić jego wartość zwracaną:

unless system('command arg1 arg2') 
    fail 
end 

Gdybym nie troszcz się o możliwość uratowania wyjątku ani o zachowaniu drukowania nieprzetworzonych wyjątków w stosach, mogę oczywiście użyć exit(1) lub w dwóch pierwszych wariantach exit($?) zamiast fail.

Jeżeli dalsze wykonanie polecenia jest ostatnią rzeczą skrypt Ruby powinien zrobić, nawet gdy polecenie powiedzie (kod wyjścia 0), mogę skorzystać z czwartego wariantu:

exec('command arg1 arg2') 

ten zastąpi Proces Ruby z nowym procesem utworzonym przez wywołanie polecenia, ale efekt dla wywołującego skryptu Ruby będzie taki sam: Widzi niezerowy kod wyjścia dokładnie wtedy, gdy wywołane polecenie spowodowało niezerowy kod wyjścia.

Bardzo podoba mi się zwięzłość czwartego wariantu, ale jeśli wykonanie polecenia nie jest ostatnią rzeczą do zrobienia w przypadku, gdy mu się uda, niestety nie mogę tego użyć. Inwokacje warunkowe w innych wariantach wyglądają bardzo nieczysto w porównaniu i w jednym przypadkowym przypadku częściej naruszają jednolity poziom abstrakcji i zasady jednej odpowiedzialności.

Mogę oczywiście napisać funkcję otoki dla każdego z trzech pierwszych podejść, aby ich użycie wyglądało tak samo zwięźle, ale ponieważ wydaje się, że jest to tak fundamentalny modus operandi, zastanawiałem się, czy Ruby ma już coś takiego wbudowany w ... czy jest to funkcja użyteczna, którą mógłbym użyć zamiast własnego opakowania lub mechanizmu, który zmienia zachowanie jednej lub kilku metod wywoływania poleceń, aby spowodować błąd lub niezerowe wyjście, gdy polecenie kończy się niepowodzeniem, analogicznie do 's i ' s option to set -e.

Odpowiedz

4

O ile wiem, nie ma wbudowanego sposób to zrobić, ale można prawie dostać żądane zachowanie przy odrobinie metaprogramowanie magicznym

def set_exit enable 
    if enable 
    define_method :system do |*args| 
     Kernel.system *args 
     exit $?.exitstatus unless $?.success? 
    end 
    else 
    define_method :system, Kernel.instance_method(:system) 
    end 
end 

set_exit true 
# ... 
# any failed system calls here will cause your script to exit 
# ... 
set_exit false 
# now system is back to normal 

ten działa poprzez przedefiniowanie system dla Object, natomiast jawnie używając Kernel.system, gdy potrzebne jest zachowanie wbudowane.

+1

Nice. Ponieważ [backquotes używają 'Kernel # \' '] (http://ruby-doc.com/docs/ProgrammingRuby/html/tut_expressions.html#UB), domyślam się, że to podejście też byłoby dla nich skuteczne. –

+0

Wow, nie wiedziałem, że to była metoda! Tak, wydaje się działać dobrze, jeśli zastąpisz ': \' 'dla': system' – Max

Powiązane problemy