Mam kilka obrazów PNG w katalogu. Mam aplikację o nazwie pngout, którą uruchamiam w celu skompresowania tych obrazów. Ta aplikacja jest wywoływana przez skrypt, który zrobiłem. Problem polega na tym, że ten skrypt wykonuje jeden po drugim, mniej więcej tak:
FILES=(./*.png)
for f in "${FILES[@]}"
do
echo "Processing $f file..."
# take action on each file. $f store current file name
./pngout -s0 $f R${f/\.\//}
done
Przetwarzanie tylko jednego pliku na raz zajmuje dużo czasu. Po uruchomieniu tej aplikacji widzę, że procesor ma zaledwie 10%. Odkryłem więc, że mogę podzielić te pliki na 4 partie, umieścić każdą partię w katalogu i uruchomić 4, z czterech okien terminala, czterech procesów, więc mam cztery instancje skryptu, jednocześnie przetwarzając te obrazy i praca zajmuje 1/4 czasu.
Drugi problem polega na tym, że straciłem czas na dzielenie obrazów i partii oraz kopiowanie skryptu do czterech katalogów, otwieranie 4 okien terminali, bla bla ...
Jak to zrobić za pomocą jednego skryptu, bez konieczności dzielenia czegokolwiek?
Mam na myśli dwie rzeczy: po pierwsze, jak przejść ze skryptu bash, odpalić proces w tle? (wystarczy dodać & na końcu?) Po drugie: jak przestać wysyłać zadania w tle po wysłaniu czwartych zadań i ustawić skrypt, aby czekał na zakończenie zadań? Mam na myśli, po prostu wysyłając nowe zadanie w tle, gdy kończy się jedno zadanie, utrzymując zawsze 4 zadania równolegle? jeśli tego nie zrobię, pętla uruchomi w tle zilliony zadań i procesor się zatka.
źródło
Odpowiedzi:
Jeśli masz kopię,
xargs
która obsługuje równoległe wykonywanie-P
, możesz po prostu to zrobićW przypadku innych pomysłów wiki Wooledge Bash zawiera sekcję w artykule Zarządzanie procesami, dokładnie opisującą to, czego chcesz.
źródło
pngout
polecenia, które chciał uruchomić OP. Kluczową opcją jest-P 4
, która mówi xargsowi, aby używał do 4 równoczesnych poleceń.printf
tu funkcji zamiast zwykłejls .. | grep .. *.png
? Byłem także zainteresowanyxargs
parametrami, których użyłeś (-0
i-I{}
). Dzięki!ls
nie można ich używać do parsowania nazw plików przenośnie i bezpiecznie . Jedynymi bezpiecznymi znakami używanymi do rozdzielania nazw plików są\0
i/
, ponieważ każdy inny znak, łącznie z\n
, może być częścią samej nazwy pliku. Doprintf
zastosowania\0
w nazwach plików ograniczają, i-0
informujexargs
o tym.-I{}
Mówixargs
zastąpić{}
z argumentem.Oprócz zaproponowanych już rozwiązań możesz utworzyć plik makefile opisujący sposób skompresowania pliku z nieskompresowanego i użyć
make -j 4
do uruchomienia 4 zadań równolegle. Problem polega na tym, że będziesz musiał inaczej nazwać skompresowane i nieskompresowane pliki lub przechowywać je w różnych katalogach, w przeciwnym razie napisanie rozsądnej reguły make będzie niemożliwe.źródło
Jeśli masz GNU Parallel zainstalowany http://www.gnu.org/software/parallel/, możesz to zrobić:
Możesz zainstalować GNU Parallel po prostu przez:
Obejrzyj wideo wprowadzające do GNU Parallel, aby dowiedzieć się więcej: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
źródło
Aby odpowiedzieć na dwa pytania:
wait
polecenia możesz poprosić powłokę, aby poczekała na zakończenie wszystkich procesów w tle, zanim przejdziesz dalej.Oto zmodyfikowany skrypt, który
j
służy do śledzenia liczby procesów w tle. KiedyNB_CONCURRENT_PROCESSES
zostanie osiągnięty, skrypt zresetuje sięj
do 0 i poczeka na zakończenie wszystkich procesów w tle przed wznowieniem jego wykonania.źródło
$f
itp. (3) Użyj[
dla skryptów zgodnych z POSIX, ale[[
zawsze preferowany jest czysty bash . W takim przypadku((
jest bardziej odpowiedni dla arytmetyki.