Czasami wykonuję długie xargs
prace z dnia na dzień i naprawdę denerwuje mnie odkrycie, że xargs
umarł gdzieś pośrodku, na przykład z powodu błędu segmentacji w jednym szczególnym przypadku, jak to miało miejsce tej nocy.
Jeśli nawet jedno xargs
dziecko zostanie zabite, nie przetwarza już żadnych danych wejściowych:
Konsola 1:
[09:35:48] % seq 40 | xargs -i --max-procs=4 bash -c 'sleep 10; date +"%H:%M:%S {}";'
xargs: bash: terminated by signal 15
09:35:58 3
09:35:58 4
09:35:58 2
<Exit with code 125>
Konsola 2:
[09:35:54] kill 5601
Czy mogę w jakiś sposób zapobiec xargs
zatrzymywaniu przetwarzania danych po śmierci procesu potomnego i kontynuować przetwarzanie?
xargs
wersji 4.4.2debian wheezy
i wygląda na to, że wszystko działa dobrze, nawet jeśli zabiję określonysleep
proces. Z której wersjixargs
korzystasz? być może rozwiązali problem w najnowszej wersji.xargs ... bash -c '...;exit 0'
a nawetxargs ... bash -c '... || echo erk'
parallel -j 1
jest to możliwe rozwiązanie hakerskie.Odpowiedzi:
Nie możesz Ze
xargs
źródeł na savannah.gnu.org :Wokół tego czeku ani wokół funkcji, która go wywołuje, nie ma flagi. Wydaje się, że ma to związek z maksymalnymi procesami, co, jak sądzę, ma sens: jeśli ustawisz wystarczająco wysokie maks. Procy, nie będzie to przeszkadzało w sprawdzaniu, dopóki nie osiągnie limitu, którym może być nigdy.
Lepszym rozwiązaniem tego, co próbujesz zrobić, może być użycie GNU Make :
Następnie:
będzie miał ten sam efekt i da ci znacznie lepszą kontrolę.
źródło
Wydawałoby się, że na jeden z najbardziej oczywistych kolokwializmów nawiązują jedynie inne propozycje.
Oznacza to, że możesz użyć następujących opcji:
w celu „wymuszenia sukcesu”.
Zauważ, że jest to zgodne z propozycją lornix (po prostu nie w wielu słowach).
W każdym razie, ponieważ skutecznie ignoruje to faktyczny status wyjścia z procesu, powinienem rozważyć zapisanie statusu podprocesu do analizy pośmiertnej. Na przykład:
true
Tutaj jest nieco zbędny i tak może to być lepiej zapisać jako:Ponieważ prawdopodobnie chcielibyśmy wiedzieć, kiedy nie można było dotknąć „nieudanego” pliku. Innymi słowy, nie ignorujemy już niepowodzenia, odnotowujemy i kontynuujemy.
Po przeanalizowaniu rekurencyjnego charakteru tego problemu, być może widzimy dokładnie, dlaczego xargs nie ułatwia ignorowania błędów. Ponieważ nigdy nie jest to dobry pomysł - zamiast tego powinieneś usprawnić obsługę błędów w rozwijanym procesie. Uważam jednak, że to pojęcie jest bardziej nieodłączne od samej „filozofii uniksowej”.
Wreszcie, przypuszczam, że właśnie o tym wspomina James Youngman, zalecając
trap
, które prawdopodobnie można by wykorzystać w podobny sposób. To znaczy, nie ignoruj problemu ... złap go w pułapkę i załatw, bo obudzisz się pewnego dnia i okaże się, że żaden z podprogramów w ogóle się nie powiódł ;-)źródło
Użyj
trap
:Ewentualnie przełącz się z powłoki na inny język, w którym można również ustawić procedury obsługi sygnałów.
Zauważ też, że po tym, jak
bash -c foo..
powinieneś podać wartość, którą$0
powinieneś przyjąć (tutajfnord
), aby pierwsze słowo wytworzone przezseq
nie zostało zjedzone.źródło
Wprowadź tam inne polecenie, aby „zjeść” sygnał z programu umierania.
Próbowałem twojego przykładu, początkowo jak pokazano, aby udowodnić problem ... „killall sleep” zabija proces snu, przerywa bash i xargs kończy pracę.
Jako test umieściłem polecenie typu „Uruchom inną komendę” pomiędzy xargs i bash ... w tym przypadku „/ usr / bin / time”. tym razem (bez gry słów) killall sleep zabija proces snu, ale xargs trwa dalej.
Skończysz przesyłać dane wyjściowe do / dev / null, a to zrobi dokładnie to, czego szukasz bez większego przepisywania istniejącego procesu.
Wyobrażam sobie, że jeśli zastanowię się przez chwilę, mógłbym wymyślić inny program, aby zrobić to samo bez gadania stderr z „/ usr / bin / time”. Lub nawet sam napisać, to tylko pochodna „fork” (lub exec ()).
Pamiętaj, aby używać „/ usr / bin / time”, ponieważ nie jestem pewien, czy wbudowany „time” z bash zrobi to samo „zjadanie” sygnału.
źródło
time
dla tego celu byłobyenv
, ponieważ wszystko, co robi, to dodać zero lub więcej opcjonalnych zmiennych do środowiska uruchomionego programu. Nie emituje żadnych danych wyjściowych, a kod powrotu wywoływanego programu zostanie przekazany z powrotem do dowolnego wywołanego programuenv
.Ani dla mnie
time
nieenv
działały (przekazują wartość zwracaną przez ich program potomny), więc napisałembliss
:następnie
chmod u+x ~/bliss
i coś w tym rodzaju
find_or_similar | xargs ~/bliss fatally_dying_program.sh
źródło