zapobiegają zamykaniu xargs w przypadku błędu


27

Według strony podręcznika xargs zakończy pracę, jeśli jeden z wierszy wykonawczych zostanie zamknięty z błędem 255:

Jeśli jakiekolwiek wywołanie polecenia zakończy się ze statusem 255, xargs zatrzyma się natychmiast bez odczytu dalszych danych wejściowych. Komunikat o błędzie jest wysyłany na stderr, gdy tak się dzieje.

Jak mogę uzyskać xargs, aby tego nie robił?

Mam około 1500 zadań wsadowych linii, które chcę uruchomić, 50 linii na raz. Odkryłem, że zawsze umiera na pewnej linii i nie kończy pracy. Niedobrze!

Jeszcze lepszym pytaniem, które opisuje to, co próbuję zrobić, jest:

Jak mogę uruchomić skrypt wsadowy o długości 1500 wierszy, po 50 wierszy jednocześnie, aby nie wychodził z zadania w środku i aby dane wyjściowe były przechwytywane do jakiegoś pliku dziennika?

Odpowiedzi:


12

Możesz owinąć skrypt perla innym prostym skryptem bash:

#!/bin/bash
real-command "$@" || exit 0

Spowoduje to wywołanie polecenia real przekazując mu wszystkie parametry przekazane do tego fałszywego polecenia i zawsze zwróci kod wyjścia 0 (co oznacza, że ​​zawsze się powiedzie), a xargs nigdy się na tym nie skończy.



9

Możesz napisać swoje wywołanie xargs, aby zamaskować kody powrotne linii poleceń. W przypadku czegoś takiego, xargsnigdy nie zobaczy kodów wyjścia zwracanych przez komendę :

xargs sh -c "somecommand || :"

Znalazłem dobre rozwiązanie: upewnij się, że przetwarzane polecenia nie wychodzą ze statusem 255! Dodatkowe szczegóły Przetwarzane polecenie jest skryptem Perla. Funkcja Perl die () była używana w kilku miejscach, aby wyjść, jeśli wystąpił jakiś błąd krytyczny (np. Nie można połączyć się z bazą danych). Jednak die () zawsze wychodzi ze statusem błędu 255. Rozwiązaniem w tym przypadku było zastąpienie die () kombinacją print i exit (), wraz z bardziej rozsądnym kodem błędu (w tym przypadku działało „1”).
JDS

6

Właśnie znalazłem zabawną odpowiedź na to pytanie, chociaż jego przydatność będzie zależeć od polecenia, które próbujesz uruchomić.

Jeśli używasz xargs w zasadzie do skompletowania listy poleceń, możesz uzyskać takie zachowanie, mówiąc xargs, aby echo polecenia, a następnie potokowanie do bash.

Na przykład, jeśli próbujesz usunąć listę rzeczy, które mogą istnieć lub nie:

# presume this will fail in a similar way to your command
cat things_to_delete | xargs -n1 delete_command_that_might_exit

# instead echo the commands and pipe to bash
cat things_to_delete | xargs -n1 echo delete_command_that_might_exit | bash

Działa to, ponieważ po pierwsze, xargs zawsze wywołuje echo, więc nie zobaczy żadnych błędów. Następnie, ponieważ domyślne zachowanie bash kontynuuje wykonywanie po nieudanej instrukcji.

Aby być bardziej szczegółowym w moim przypadku, użyłem tego, aby usunąć kilka starych wersji aplikacji z AWS ElasticBeanstalk w następujący sposób:

aws elasticbeanstalk describe-application-versions --application-name myapp |\
jq -r '.ApplicationVersions | sort_by(.DateCreated) | .[0:-10] | .[].VersionLabel' |\
xargs -n1 \
  echo aws elasticbeanstalk delete-application-version \
       --delete-source-bundle --application-name myapp --version-label |\
bash

4

Następujące prace budowlane dla mnie:

ls | xargs -I % svn upgrade %

Nawet jeśli aktualizacja jakiegoś elementu zakończyła się niepowodzeniem, proces był kontynuowany


3

Jeśli korzystasz xargsz find, użyj -execopcji findzamiast:

find . -name '*.log' -exec somecommand {} \;

1
cześć. Mógłbym tego użyć, ale opcja -exec nie wykonuje operacji równoległych w taki sam sposób, jak przy użyciu xargs
JDS

2
Dziękuję - nie wiedziałem, że xargsmożna uruchamiać polecenia równolegle. Fajne. Jeśli chcesz tylko zminimalizować liczbę wywołań poleceń, -execma +parametr.
Roger Dahl
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.