PlayStation Network (PSN) má již několik hodin, vlastně celou sobotu, masivní výpadek (Stav služby PSN, X).
Vývojáři open source storage platformy TrueNAS oznámili, že s verzí 25.04 s kódovým názvem Fangtooth končí TrueNAS CORE postavený na FreeBSD a TrueNAS SCALE postavený na Linuxu. Jejich společným pokračováním bude TrueNAS Community Edition postavený na Linuxu.
Mapy Google dnes slaví 20 let. Spuštěny byly 8. února 2005. Svět se přesunul od papírových map k digitálním. A ke Street View, Live View, Immersive View, …
Hector "marcan" Martin, vedoucí projektu Asahi Linux aneb Linux na Apple Siliconu, skončil jako upstream vývojář linuxového jádra. Se slovy "už nemám žádnou důvěru v proces vývoje jádra … další vývoj Apple/ARM bude pokračovat downstream" odstranil své jméno ze souboru MAINTAINERS. Důvodem jsou neshody kolem Rustu v linuxovém jádru [Hacker News, No rust code in kernel/dma, please.].
Mistral AI včera představil nový vylepšený Le Chat. Nově také jako aplikace pro iOS a Android.
Britské bezpečnostní orgány nařídily americké firmě Apple, aby vytvořila takzvaná "zadní vrátka", která by umožnila dostat se k šifrovanému obsahu uživatelů uloženému v cloudu. Tajné nařízení, vydané v lednu, vyžaduje plošný přístup k šifrovanému účtu jakéhokoliv uživatele přístrojů Apple kdekoliv na světě. Britské úřady tedy Apple nežádají pouze o asistenci s přístupem k účtu konkrétního uživatele, ale rovnou chtějí mít přístup ke všem účtům, kdykoliv budou chtít.
Byla vydána (𝕏) lednová aktualizace aneb nová verze 1.97 editoru zdrojových kódů Visual Studio Code (Wikipedie). Přehled novinek i s náhledy a animovanými gify v poznámkách k vydání. Ve verzi 1.97 vyšlo také VSCodium, tj. komunitní sestavení Visual Studia Code bez telemetrie a licenčních podmínek Microsoftu.
Nedávno se povedlo do pdf souborů vložit Tetris a DOOM a po otevření příslušného pdf souboru v na Chromiu založeném webovém prohlížeči vybranou hru přímo v pdf spustit. LinuxPDF ukazuje, že do pdf lze vložit také RISC-V emulátor a rozběhnout Linux.
Kancelářský balík LibreOffice byl vydán ve verzi 25.2. Podrobnosti v poznámkách k vydání.
Program parallel
je naprogramovaný v Perlu a je parádní zejména pro paralelizaci činnosti jiných nástrojů, které to implicitně nepodporují.
Než si budete jisti jak se parallel
chová, doporučuji jej spouštět nejdřív s přepínačem --dry-run
, který pouze vypíše jaké příkazy by byly spuštěny. V ukázkách jej neuvádím, tak si jej dle potřeby doplňte. Potom možná v některých případech budete chtít použít přepínač -v
, aby parallel
za běhu vypisoval příkazy, které spouští.
Například toto konvertuje všechny MP3 soubory na WAV rekurzivně vůči aktuálnímu adresáři:
find ./ -iname '*.mp3' -type f -print0 | parallel -0 -v -- lame --decode
V této ukázce find
dodá seznam cest k MP3 souborům (kde jednotlivé cesty jsou odděleny speciálním znakem \0
, který se v Linuxu jako jediný nesmí vyskytovat v cestě k souboru) na vstup programu parallel
, kterému přepínačem -0
řekneme, aby použil jako oddělovač znak \0
(výchozí oddělovač je \n
, tedy nový řádek, přičemž libovolný jiný oddělovač lze nastavit přepínačem --arg-sep
). Potom (volitelně) explicitně ukončíme seznam přepínačů pomocí --
(čímž zajistíme, aby nebylo možné další argumenty zaměnit za přepínače programu – toto je velmi žádoucí používat ve skriptech, kde předem neznáte argumenty příkazu, neboť jsou např. složeny pomocí proměnných ze vstupů uživatele) a nakonec uvedeme příkaz, který se má nad jednotlivými soubory vykonat (zde lame --decode
, jež převede zadanou MP3 na WAV).
Příkaz se spustí jednou pro každý soubor, a to paralelně v N instancích 1:1 dle počtů procesorových jader, kterými systém disponuje. Počet souběžných procesů lze ovlivnit přepínačem -j
– tomuto přepínači můžete zadat celé číslo x
pro uvedení počtu paralelně běžících procesů nebo případně číslo se znaménkem plus či mínus pro spuštění max. N+x
nebo N-x
paralelních procesů (kde N
je počet jader a x
je celočíselný argument se znaménkem).
Tohle byla triviální ukázka, kterou stejně tak dobře zvládnou nástroje xargs
a xjobs
, které dále v článku také představuji. Pojďme se podívat na zajímavější příklady.
Co třeba když potřebujeme „grepnout“ gigantický textový soubor na výskyt nějakého řetězce? Úložiště je rychlé (anebo je soubor nakešovaný), ale grep
paralelně nepracuje – co s tím? Třeba toto:
parallel --pipe --block 20M -- grep --color=always substring < bigfile
V této ukázce parallel
vezme data ze standardního vstupu (--pipe
) a rozdělí je na bloky po 20 MB (--block 20M
; delší řádky automaticky zvětší velikost bloku) a nad každým blokem se spustí instance programu grep
(s přepínačem --color=always
, který vynutí barevné odlišení odpovídajícího řetězce).
Tento přístup má své nevýhody, ale do jisté míry je možné je řešit. Například když chcete použít grep
s přepínačem -n
, abyste viděli na jakém řádku se hledaný text vyskytuje, tak s tímto postupem samozřejmě narazíte, protože každý blok má řádky číslované od 1. Řešením může být toto:
nl bigfile | parallel -k --pipe --block 20M -- grep --color=always substring
Pomocí nl
(nebo alternativně lze použít cat -n
) si na začátek každého řádku vypíšeme jeho pořadové číslo a pak ještě (volitelně) předáme programu parallel
přepínač -k
, který zajistí, aby se výstup vypisoval ve správném pořadí (v tomto případě po zpracování datových bloků od prvního k poslednímu, takže každé další číslo řádky s výskytem hledaného řetězce bude vyšší než to předchozí).
Pozor, tento trik s číslováním řádků mimo grep
má jednu nevýhodu. Program nl
zde samozřejmě musí soubor sekvenčně přečíst a zpracovat, takže soubor nelze jen tak přečíst z keše a bude to o něco pomalejší. Toto není zásadní problém, neboť tato operace je obecně výrazně rychlejší než hledání regulárního výrazu v textovém souboru, ale je dobré si to uvědomit. Zrovna tak je potřeba mít na paměti, že ne vždy toto paralelní spouštění grep
u bude rychlejší než když jej spustíte jen tak, protože spouštění více instancí přidává navíc nějakou režii. Dle mých testů se vyplácí zapojit parallel
až když hledáte nějaký netriviální regulární výraz.
Mimochodem, grep
může být mnohem rychlejší, když mu nastavíte základní locale „C" místo nějaké UTF-8 locale jako je třeba “cs_CZ.UTF-8", ale samozřejmě je potřeba vždy zvážit, zda je tato změna žádoucí.
Nyní trochu odbočím: pokud vezmete ukázkový příkaz a nahradíte „substring“ za složitější výraz obsahující mezery anebo různé speciální znaky, tak zjistíte, že se to celé nechová tak, jak byste chtěli. Ukázka, která nebude fungovat:
nl bigfile | parallel -k --pipe --block 20M -- grep --color=always "substring test"
V tomto případě je potřeba předat nástroji parallel
přepínač -q
, který provede escapování znaků, které mají v shellu speciální význam. Správně je to tedy takto:
nl bigfile | parallel -qk --pipe --block 20M -- grep --color=always "substring test"
nebo alternativně příkaz spustit bez -q
takto (escapování provádíme sami):
nl bigfile | parallel -k --pipe --block 20M -- grep --color=always '"substring test"'
Přepínač -q
(--quote
) není ve výchozím stavu aktivní, protože většinou to není potřeba a rozbíjí to jinou zajímavou funkcionalitu; například s -q
není možné spustit něco jako:
ls *.gz | parallel -q "zcat {} | bzip2 > {.}.bz2"
Příkaz výše by bez -q
vytvořil pro každý gzip archív v adresáři jiný archív typu bzip2 se stejným obsahem. Ovšem s -q
toto není možné, protože mezery, znaky pipe |
i znaky přesměrování >
byly escapovány a vzniklý příkaz se nyní chová jako kdybyste ho do konzole zadali jako jeden dlouhý argument. Nedopadne to dobře. Nechceme-li tedy přijít o možnost spouštět takto komplexní příkazy, musíme se o escapování postarat sami.
V první ukázce jsem využil toho, že program lame
automaticky vytvoří výstupní soubor pojmenovaný stejně jako vstupní, pouze korektně změní příponu. Toto vám jednak u všech programů neprojde a navíc ne vždy je to žádoucí, takže si ukažme jak se to dá řešit.
Vytvoříme všem JPEG obrázkům v aktuálním adresáři malý náhled pomocí nástroje convert
z balíčku ImageMagick. Nejdřív pro jeho snadnost ukážu krátký zápis a potom teprve korektní zápis:
ls *.jpg | parallel convert -resize 25% '{}' '{.}-small.jpg'
nebo
parallel convert -resize 25% '{}' '{.}-small.jpg' ::: *.jpg
(Druhý příkaz je ukázkou toho, že parallel
umí převzít seznam souborů i jako své argumenty, jen je potřeba je uvést za oddělovač :::
.)
Opět příkazu parallel
předáme seznam souborů ke zpracování. Na název souboru se můžeme odkázat pomocí řetězce {}
, přičemž tento lze různými způsoby modifikovat, např. {.}
vrátí vstupní až k poslední tečce (tzn. bez přípony).
Toto vám ve většině případů bude fungovat a asi bych to tak sám zapsal pro jednorázové zpracování, ale nedoporučoval bych to tímto způsobem spouštět ve skriptech. Je zde totiž několik problémů. Nahrazení *.jpg za seznam všech souborů, jejichž názvy končí na „.jpg“, provádí shell a nikoliv ls
, takže když máte v aktuálním adresáři velmi mnoho takových souborů (anebo klidně málo, ale s velmi dlouhými názvy), tak vám ls
klidně může vypsat chybu argument list too long
. Další věc je, že nemáte jistotu, že se v seznamu neobjeví adresář – stačí když jeho název končí na „.jpg“ a v seznamu se objeví a budou tím pádem do zpracování zahrnuty i všechny soubory v tomto adresáři nezávisle na jejich příponě. A to stále není vše; soubory mohou v názvu obsahovat i znak nového řádku (lze vytvořit v bashi např. příkazem touch $'a\nb'
a smazat pomocí rm -- $'a\nb'
), s čímž si příkaz výše také neporadí a bude brát část před novým řádkem a část za ním jako dva odlišné názvy souborů. Řešením je použít:
find ./ -maxdepth 1 -iname '*.jpg' -type f -print0 | parallel -0 -- convert '{}' '{.}-small.jpg'
Toto navíc jako bonus vyhledá soubory s příponou .jpg
bez ohledu na velikost písmen (tzn. jako kdybychom výše napsali ls *.[jJ][pP][gG]
).
Další základní vlastností je samozřejmě možnost paralelně spustit seznam příkazů zapsaných v souboru:
parallel < /tmp/command_list
anebo
parallel :::: /tmp/command_list
Jak je vidět, parallel
umí přečíst seznam argumentů ze zadaného souboru i přímo, stačí jej uvést za čtyři dvojtečky (oproti třem dvojtečkám, když chcete uvádět argumenty přímo na příkazovém řádku, viz výše).
Někdy se vám možná stane, že budete chtít vidět seznam procesů, které má parallel
spuštěné. Vypíše vám je, když mu pošlete signál SIGUSR1
. Když si budete přát ukončit parallel
, ale nepřerušovat již spuštěné procesy, pošlete mu signál SIGTERM
a program nechá doběhnout to, co již spustil, a pak se ukončí.
Když si definujete funkci v bashi a budete ji chtít spouštět pomocí parallel
, nezapomeňte ji neprve exportovat:
RePack() { zcat -- "$1" | bzip2 -9c > "${1%.*}.bz2" && rm -f -- "$1"; } export -f RePack parallel RePack ::: *.gz # ve skriptech radši použijte find místo wildcard, viz výše
Než vás odkážu na velice obsáhlý manuál pro více příkladů, ukážu ještě jedno použití, které se mi líbí. Když nějaký program, který voláte přes parallel
, umí zpracovat více argumentů najednou, můžete toho využít díky přepínači -X
, který rozdělí seznam vstupů tak, aby se jich každé spouštěné instanci předalo co nejvíce a v případě potřeby je rovnoměrně rozdělí mezi zadaný počet instancí.
Takže pak můžete spustit něco jako:
parallel -j 8 -X oggenc ::: *.wav
Bude to fungovat podobně jako:
oggenc *.wav
ale s tím rozdílem, že parallel
seznam souborů WAV rovnoměrně rozdělí mezi osm instancí oggenc
.
Přepínačem -N
lze shora omezit počet argumentů, které program dostane.
Pro více informací zkuste omrknout:
man 1 parallel man 1 parallel_tutorial
Dozvíte se například to, že parallel
umí distribuovat práci i na vzdálené počítače pomocí SSH tak, že tam nakopíruje soubory ke zpracování, paralelně je začne zpracovávat a každý výsledný soubor ihned zase přenese zpátky a uklidí po sobě na vzdálené straně. To se hodí, když máte mezi počítači velmi rychlou síť a váš stroj má pomalý procesor (anebo když třeba zcela postrádá požadovanou funkcionalitu).
parallel --sshlogin node01.lan --trc /tmp/{/.}.wav oggdec {} -o /tmp/{/.}.wav ::: *.ogg
Přepínač --trc
je zkratkou --transfer
(přenes na vzdálenou stranu), --return
(výsledek nakopíruj zpět) a --cleanup
(ukliď po sobě). Je potřeba mu dát jako argument šablonu názvu souboru, který se má zkopírovat zpátky ze vzdáleného serveru. Dodám, že {/.}
je nahrazeno za název souboru bez cesty a bez přípony, tedy z cesty /home/test/soubor.txt
vznikne podřetězec soubor
, čehož jsem využil pro dodání vlastní cesty (/tmp
) a vlastní přípony (.wav
).
Podělte se prosím v diskuzi, pokud vás napadne nějaké pěkné využití programu, které jsem nezmínil.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
Diskuse byla administrátory uzamčena
Takžeparallel --sshlogin node01.lan --trc /tmp/{/.}.wav oggdec {} -o /tmp/{/.}.wav ::: *.ogg
Dodám, že{./}
je nahrazeno za název ...
{./}
nebo {/.}
?
{/.}
- díky za upozornění, opravil jsem to v článku.
#!/bin/dash Pozdrav="() { echo ahoj; }" export Pozdrav bash -c PozdravJe otázka ale jaký shell použije ten příkaz parallel. (Dá se pak asi z parallel spustit "bash -c Funkce" ale to už začíná být dost přes ruku.
cd /var/tmp wget http://ftp.linux.cz/pub/FILES.byname # textovy soubor cca 1.1 GB for i in `seq 1 20` ; do time sh -c 'grep -n jezek FILES.byname >/dev/null'; done for i in `seq 1 20` ; do time sh -c 'nl FILES.byname | grep jezek >/dev/null'; doneU mě první varianta běží cca 1.9 s reálného času (okolo 1.1 user, 0.8 system), druhá varianta 6.6 s reálného času (7.0 user, 1.5 system). Beru vždy nejrychlejší čas z těch 20 pokusů. Nicméně zdá se, že samotný výpočet nad daty z cache taky není úplně zadarmo - když spustím ten první případ bez -n (bez počítání čísel řádků), tak je to ještě o dalších 0.2 s rychlejší. -Yenya
parallel
podporoval paralelní čtení z jednoho souboru - že by každý proces četl od jiného offsetu nějakou danou velikost, ale to by šlo samozřejmě jen tehdy, kdyby se nemusely hlídat konce řádků a práce by se rozdělovala dle fixní velikosti.
parallel
a volaným programům by se pak chunky předávaly třeba na vstup nebo přes pojmenovanou rouru, atd.