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?

JDS
źródło

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.

użytkownik842313
źródło
24

Podobne do larsksodpowiedzi, ale bardziej wyraźne:

xargs sh -c "somecommand || true"
Filippo Vitale
źródło
używając sh -cdla mnie wors!
hukeping
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 || :"
Larsks
źródło
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
matschaffer
źródło
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

AndreyP
źródło
3

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

find . -name '*.log' -exec somecommand {} \;
Roger Dahl
źródło
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