2012-10-26 14 views
5

muszę wdrożyć BASH „set -o pipefail” opcję w sposób POSIX tak, że działa na różnych smakach Linux/UNIX . Aby wyjaśnić nieco, ta opcja umożliwia użytkownikowi sprawdzenie pomyślnego wykonania wszystkich poleceń potokowych. Po włączeniu tej opcji to polecenie cat app.log | grep "ERROR" kończy się niepowodzeniem, jeśli "cat" zawodzi, w przeciwnym razie błąd "cat" zostaje stłumiony.Jak wdrożyć „set -o pipefail” w sposób POSIX - prawie gotowe, ekspert potrzebna pomoc

Tak, znalazłem bardzo ładne rozwiązanie tutaj: http://cfaj.ca/shell/cus-faq-2.html

 run() { 
     j=1 
     while eval "\${pipestatus_$j+:} false"; do 
      unset pipestatus_$j 
      j=$(($j+1)) 
     done 
     j=1 com= k=1 l= 
     for a; do 
      if [ "x$a" = 'x|' ]; then 
      com="$com { $l "'3>&- 
         echo "pipestatus_'$j'=$?" >&3 
         } 4>&- |' 
      j=$(($j+1)) l= 
      else 
      l="$l \"\$$k\"" 
      fi 
      k=$(($k+1)) 
     done 
     com="$com $l"' 3>&- >&4 4>&- 
        echo "pipestatus_'$j'=$?"' 
     exec 4>&1 
     eval "$(exec 3>&1; eval "$com")" 
     exec 4>&- 
     j=1 
     while eval "\${pipestatus_$j+:} false"; do 
      eval "[ \$pipestatus_$j -eq 0 ]" || return 1 
      j=$(($j+1)) 
     done 
     return 0 
     } 

Funkcja ww run() umożliwia użytkownikowi powoływać się rurami polecenia w taki sposób: uruchom cmd1 \| cmd2 \| cmd3 Jeśli jedno z poleceń nie powiedzie dostajesz to w $?

Istnieje jednak problem, że nie obsługuje grupowanie poleceń między rurami. Chcę móc wywołać coś takiego:

run echo "test" ; grep "test" \| awk '{print}' 

Kiedy to zrobię, wywołanie nie powiedzie się. Nie mogę uzyskać prawo modyfikacji w celu wsparcia grupowania komend - skrypt jest nieco zbyt skomplikowane dla moich umiejętności bash ... Może ktoś pomóc?

Dzięki!

Jest definicja funkcji run(), która umożliwia użytkownikowi uruchomić rurami polecenia w taki sposób:

+0

';' nie grupuje poleceń między rurami w bash. '(...; ...)' lub '{...; ...; } 'robi. – choroba

+0

'set -o pipefail'. 'set -e' jest inne. Jest to możliwe, ale prawdopodobnie więcej wysiłku niż jego wartość. Ksh obsługuje również pipefail, a mksh obsługuje 'PIPESTATUS', który może być łatwo użyty do implementacji pipefail. Poważnie rozważam używanie innego języka przed próbą tego w POSIX sh. – ormaaj

+0

@choroba - to właśnie miałem na myśli. Masz rację. To też nie działa. –

Odpowiedz

3

Po wpisaniu:

run echo "test" ; grep "test" \| awk '{print}' 

wywołać run z argumentami echo i "test"; następnie wywołać grep z argumentami "test", |, awk i {print}. Zazwyczaj grep nie zamierza znaleźć dowolny z plików zwanych |, awk lub {print}.

Aby wywołać run jak chciałeś, trzeba uciec się średnik jak zrobiłeś | (i trzeba by robić rzeczy, podobnie do && lub || lub & i ewentualnie innych składników linii poleceń ; należy dokładnie przemyśleć sposób postępowania z $(...) lub backticks `...`).

Jeśli piszesz:

run echo "test" \; grep "test" \| awk '{print}' 

będzie przynajmniej uzyskać wszystkie argumenty zamierzałeś run. Czy to działa, jest dyskusyjne; Nie rozumiem jeszcze, jak powinien wyglądać Twój kod run.

[... Następnie ...]

to ma pewne groźnych przekierowania I/O, ale zawija każdy segment polecenia oddzielone kreską w oddzielnym małym pakietem hieroglifów. Zakłada się, że zawijanie podwójnych cytatów wokół argumentu neutralizuje go poprawnie, co nie zawsze jest prawdą (choć jest to prawdą przez większość czasu).

0

Napisz własną powłokę w standardowym C lub załóż standardową powłokę lub użyj istniejącej powłoki z czymś takim jak -o pipefail.

Najwyraźniej -o pipefail to ważna cecha, która powinna znajdować się w standardowej powłoce, a jeśli zadasz mi pytanie, te hacki naśladujące ją w standardowej powłoce są brzydkie i gorsze niż bezużyteczne.

Powiązane problemy