Przerwij zadanie wsadowe między plikami

2

Muszę skonfigurować moje zadanie wsadowe bash (kompresowanie plików 5.1k na miejscu), aby jeśli trzeba było zatrzymać / wznowić zadanie, poczekał, aż znajdzie się ono „między” plikami (właśnie skończył jeden i nie uruchomił innego).

Moja kompresja wyglądałaby tak, pigz -9 -- rsnc*jakby wszystkie działały jednocześnie, i zastanawiałem się nad czymś takim:

ls rsnc* | while read file 
  do pigz -9 -- $file
  if [ -f .intr ]
    then break
  fi
done

Czy to niezawodny sposób na osiągnięcie mojego celu? Czy jest lepszy sposób?

Camden Narzt
źródło
Jeśli musisz tylko zawiesić, możesz użyć Ctrl-Z. Odpowiada numerem zadania (na przykład [3]) na liście zadań. Następnie możesz go wznowić za pomocą %3.
Hastur
Nie, muszę go zatrzymać, ponieważ musiałbym odłączyć zewnętrzny dysk w przypadku, gdy musiałem zatrzymać partię.
Camden Narzt,

Odpowiedzi:

2

Można trap [ 1 ], [ 2 ]Ctrl + Csygnał INT jeden, a waitna zakończenie każdego procesu.

#!/bin/bash

trap ctrl_c INT

function ctrl_c() {
        wait   # wait for the end of all child processes    
        exit   # <<--- put here your exit code exit 1, ... 
}

shopt -s nullglob
for f in rsnc*
do
    pigz -9 -- $file &   # Execute in background
    wait  $!             # Wait for the end of the last command 
done

Uwaga
Istnieje wiele sposobów przełączania wszystkich plików w katalogu [ 3 ] , ale zawsze lepiej jest unikać analizowania danych wyjściowych ls [ 4 ] .

Bibliografia

Hastur
źródło
Dziękujemy za wskazanie zagrożeń związanych z analizą ls, choć w tym przypadku wszystkie nazwy plików są znane. Zastanawiam się, dlaczego tło, a pigznastępnie czekać na to? czy uruchomienie pigz na pierwszym planie nie przyniosłoby tego samego? $!Jest również ogólnie ostatnim argumentem do poprzedniego polecenia, czy to oznacza coś jeszcze tutaj?
Camden Narzt,
Nie ma za co. :) 1. Zawsze jest możliwe, że istnieje plik, którego nie sprawdziłeś, lub że w dalekiej przyszłości ponownie użyjesz innych plików (i zapomnisz o tym). 2. W tle, bo inaczej przerwiesz w środku pigz 3. Nie $!zwraca PID ostatniego polecenia wykonanego w tle ( &).
Hastur
Tutaj wait $! zrób to samo z prostego wait. Oczywiście będzie inaczej, jeśli chcesz uruchomić n czasu równoległego pigzna różnych plikach i poczekać, aż liczba procesów potomnych będzie mniejsza niż n . (Nie będziesz potrzebować więcej wait $!niż kolejny cykl, z testem i snem ...). pigzTrwa to, jeśli chcesz uruchomić kilka równolegle i poczekać na ostatnią. ps> możesz złapać inny sygnał, jeśli wolisz ...
Hastur
Ups, myślałem !$. Tak, nie mogę działać pigzrównolegle, ponieważ używa już wszystkich moich rdzeni na poszczególnych plikach (ale na pewno jest szybki); ale to nie jest problem z twoją odpowiedzią, tylko niektóre informacje. Pomyślałem, że skoro przewodnik INTwoła wait, że pigzna pierwszym planie wciąż będzie czekać, a nie minie INT? Nie próbując sugerować, że się mylisz, po prostu mile widziane byłoby dodatkowe wyjaśnienie przepływu kontroli.
Camden Narzt,
Jeśli dobrze rozumiem wynik, help waitgdy mówi: Jeśli identyfikator nie zostanie podany, czeka na wszystkie aktualnie aktywne procesy potomne i status zwrotu ... wydaje się sugerować, że jeśli nie jest w tle &lub w podpowłoce (), nie jest dziecko jeden i nie należy się spodziewać, że waitbędzie czekać na niego. Możesz przetestować (to ciekawe). ps> Możesz złapać w pułapkę nawet inny sygnał, jeśli chcesz ... a od systemu do systemu może zmieniać nazwę sygnału (zwykle kill -ldla listy).
Hastur