2011-08-16 16 views
9

Używam Perla 5.10.1 na Ubuntu 11.04. Chcę, aby Perl wykonywał skrypt powłoki i kończy pracę z tym samym kodem, który kończy skrypt powłoki. Ale to nie działa dla mnie ...Uzyskiwanie Perla w celu zwrotu poprawnego kodu wyjścia

system($runCmd) or die("Failed to run \"$runCmd\": $!"); 

I potwierdziły, że uruchomienie „$ runCmd” sam zwraca kod zakończenia 255, ale „die” klauzula nie jest uzyskiwanie wywołany. Jak wyjść z poprawnym kodem lub co najmniej nie udać się dla kodów niezwiązanych z powodzeniem?

Innym drobnym wymaganiem jest to, że chcę, aby dane wyjściowe z $ runCmd były drukowane na ekranie.

Odpowiedz

8

Jako perldoc -f die mówi, die nie daje konkretnego kodu wyjścia (tylko niezerowy kod wyjścia). Aby uzyskać to, co chcesz, musisz coś takiego:

my $exit_code=system($runCmd); 

if($exit_code!=0) 
{ 
    print "Command $runCmd failed with an exit code of $exit_code.\n"; 
    exit($exit_code >> 8); 
} 
else 
{ 
    print "Command $runCmd successful!\n"; 
} 
+8

Potrzebujesz: 'exit ($ exit_code >> 8)'. – ErikR

+0

Dlaczego tak jest? –

+3

Wartość zwrócona przez 'system()' jest liczbą całkowitą, która koduje wartość wyjściową procesu potomnego plus flagi wskazujące, w jaki sposób proces potomny został zakończony (normalne zakończenie, zabite przez sygnał itd.) Wartość przekazana do 'wyjścia () 'jest po prostu wartością wyjściową. – ErikR

6

Jeśli system zwraca 255, potrzebujesz warunku and.

system zwraca zero na udanej realizacji. Ponadto die zmodyfikuje kod wyjścia skryptu. Zamiast warn i powrócić ostatni kod wyjścia tak:

system($cmd) and do { 
    warn "Failed to run $cmd. Exit code is $?"; 
    exit $? >> 8; 
}; 

Aby złapać wyjście programu, należy użyć znaku odwróconego apostrofu (`) Operator:

my $output = `$cmd`; 

if ($?) { 
    warn ...; 
    exit $? >> 8; 
} 

Operator grawis rejestruje tylko STDOUT, więc dla wszystkie komunikaty o błędach (które zwykle przechodzą do STDERR), które należy przechwycić, zmodyfikować $cmd i dołączyć do niego 2>&1.

Zauważ lewe przesunięcie o osiem bitów na globalnym $?.


kuponów iść do @musiKk: The perl documentation on system() stany jak poprawnie odzyskać status wyjścia rzeczywisty.

+3

Tylko dodatek: Musisz przesunąć wartość zwracaną przez 'system' o osiem w prawo, aby uzyskać wartość zwracaną' $ cmd'. (http://perldoc.perl.org/functions/system.html) – musiKk

+0

Dzięki, @musiKk. Odpowiednio zaktualizowałem swoją odpowiedź. –

4
system($runCmd) or die("Failed to run \"$runCmd\": $!"); 

przeciwieństwie do większości funkcji Perl, system zwraca false gdy to się uda i prawdziwe, jeśli nie powiedzie się. Jest to całkowicie wstecz, wiem, ale tak właśnie jest.

Potrzebujesz "system() i" nie "system() lub". Prawdopodobnie nie potrzebujesz $?, nie $!, chociaż czasami może to być trudne.

mam niewielką awersję do

system(...)       && die 

ponieważ śruby up cała reszta || die „s, które zwykle sprawiają ciągłą pionową podwójną marżę w sprawie prawa, czasami napisać

system(...) == 0      || die 

, tak aby wszystkie znowu poprawnie się ułożyły.

0

Jeżeli układ() 's pozorny zacofanie przeszkadza, zawsze można uczynić je bardziej znośnym robiąc coś takiego:

my $err = system '/something/that/may/not/work'; 
if ($err) { 
    warn "@{[$! || 'undefined error']}\n"; 
    exit $err >> 8; 
} 

Twój $ runCmd, BTW, jeśli drukuje go na ekranie (i to jest uruchomione z wiersza poleceń i nie przekierowałeś wyjścia itp.) zostanie wydrukowane na ekranie. Po prostu IT wydrukuje go na ekranie. Perl nie ponosi za to odpowiedzialności ani nie wie (lub nie obchodzi), co drukuje. Jeśli to wszystko, czego chcesz, i nie chcesz systematycznie analizować ani przetwarzać wyników działania $ runCmd, jesteś złoty. Wypróbuj:

perl -e "system 'ls -Fahl'" 

Nie będzie też kolidować ze STDOUT $ runCmd. To też przejdzie do twojego terminalu. Na przykład:

$ perl -e "system 'ls -Fahl /dev/null/something' and die qq(fail: $! >> 8 == @{[$! >> 8]})" 
ls: /dev/null/something: Not a directory 
fail: 26205 >> 8 == 102 at -e line 1. 
Powiązane problemy