e-x-a.org » NSWI095 Úvod do UNIXu

Informace o cvičení k přednášce Úvod do UNIXu — SU2, čtvrtky ve 14:00, LS 2017/18.

  • V případě čehokoliv mi napište mail na kratochvil@ksi.mff.cuni.cz
  • Materiál ke čtení:
    • Knížka Libora Forsta “Shell v příkladech” jde půjčit v knihovně (dostupné množství se před zkouškovým výrazně ztenčuje)
    • Advanced Bash Scripting Guide
    • StackOverflow a wikipedia (s rezervou!)
    • Po internetu se povaluje hromada materiálu typu ‘Sed by example’, ‘Awk by example’, apod. Manuálové stránky jsou taky online.

Požadavky na zápočet

Zápočet je potřeba k přihlášení na zkoušku, všichni by ho měli dostat ideálně do začátku zkouškového. Předem upozorňuju, že přes zkouškové a v září budu k dispozici tak napůl.

Zásadním účelem zápočtu je zajistit, že až půjdete ke zkoušce, tak odejdete s úspěchem a zkoušející z toho nebude muset mít těžkou hlavu a černé myšlenky. O této schopnosti mě můžete přesvědčit jakýmkoliv dostatečně rigorózním způsobem, doporučené postupy jsou ale tyto:

  • Spolehlivá metoda: Zápočet lze dostat za domácí úkoly, zápočťák a aktivitu.
    • Domácí úkoly budu zadávat každý týden, budou obecně dost jednoduché, odevzdávat je budeme nově přes git. Bude potřeba sesbírat aspoň 50% bodů. Termín je vždy do poslední půlnoci předcházející dalšímu cvičením.
    • Zápočťák je jakýkoliv program, který implementuje něco zajímavého/užitečného/zábavného v shellu, awku, sedu, nebo podobné unixovině, není k dispozici v miliardě kopií na internetu a má rozumný rozsah. Více viz. níže.
    • Aktivita bude probíhat podobně jako na mých ostatních cvičeních — za programování na projektor/nějakou práci u tabule dostanete bod. Doporučuju nemít nápadně málo aktivitních bodů.
  • Rychlá a těžká metoda: Pokud se nechcete zdržovat s něčím co už umíte, můžete na jednom z prvních cvičení napsat těžkou písemku spočívající ve vypracování nějakého pitoreskního ale zvládnutelného zadání v shellu/sedu/awku v časovém limitu cvičení. Dejte mi předem vědět mailem, ať vyrobím nějaké zadání. Zápočet za zvládnutí a rozumný kód je okamžitý.

Mezivýsledky můžete sledovat zde.

Pokud na zápočet potřebujete doplnit body za domácí úkoly, napište mi.

Témata na zápočťáky

Téma zápočťáku je potřeba dohodnout do 22. 4. 2018. Pokud jste už vytvořili něco jiného co s UNIXem souvisí, neváhejte to použít jako zápočťák.

VHODNÉ:

Rozsah: orientačně cca nad 100 a pod 400 řádků kódu. Víc není problém, ale hrozí, že toho bude zbytečně moc. Míň taky není problém, pokud kód bude dostatečně funkčně nahušťěný.

Témata:

  • zábavné náhrady nějakých shellových příkazů (simple parallel make, tiny almost-git, ...)
  • databázoviny
    • systém na evidenci nějakých věcí (knihovna, fotbalova liga, ...) s “konzolovým” “user” “interfacem”
    • mailing list management daemon
  • časoviny a kalendářoviny
    • ToDo manager
    • miniaturní cron daemon
    • kreslítko kalendáře, v něčem lepší než standardní cal
  • hry
    • textové hry
    • multiplayerové hry (piškvorky, chat, MUD, ...) pomocí netcatu
    • něco co kreslí do terminálu skoro grafiku (inspirace viz. rash, 0verkill, nethack)
  • zálohovací nebo verzovací věci (viz. rdiff-backup apod.)
  • programování
    • zvýrazňovače, zarovnávače, zkrášlovače a čističe kódu
    • interpretery, např. interpret Logo (želvičky) nebo něčeho podobného (robot karel?) — vhodné, rychlé a jednoduché řešení je přepsáním zdrojáku sedem do nějakého jiného jazyka a spuštění výsledku již existujícím interpreterem/kompilátorem.
    • build systémy/balíčkovače (např. něco co pro projekt v C++ vygeneruje přenosný Makefile, (anti)inspirace viz. např. CMake)

NEVHODNÉ:

  • cokoliv co jde vygooglit v mnoha a mnoha kopiích
  • zadání jehož smysl nepochopím do 3 minut
  • řešení které celé nepřečtu do 20 minut
Hodnocení zápočťáků

Hodnotí se následující aspekty (seřazené sestupně podle důležitosti). Pokud máte přebytek aktivitních bodů, můžete ho vyměnit za úlevy na méně důležitých bodech:

  • nejdůležitější součást — odevzdání ve formě podle návodu dole
  • rozsah (Horní hranice: dokážete to celé vysvětlit za 10 minut a za dalších 15 minut jde prozkoumat celý zdrojový kód. Spodní hranice: složitost by měla převyšovat domácí úkoly z konce semestru.)
  • pokrytí funkcionality demonstrativním kódem a dokumentací (do minuty si to můžu úspěšně celé vyzkoušet)
  • absence programovacích chyb (tj. např. program nejde rozbít špatným vstupem)
  • dodržení standartnosti v tom, jak se program chová uvnitř (např. kde má uložená pevná data a konfiguraci, dočasná data, jestli správně používá ostatní programy)
  • dodržení UNIXové “slušnosti” interfacu (tj. nahlášení chyby exit kódem, standartní reakce na standartní optiony (--help), chybové hlášky na stderr)
  • kvalita kódu (odsazování, komentáře, názvy proměnných, jde to přečíst/pochopit bez bolení očí/hlavy)
Jak odevzdat zápočťák?

Pošlete mi ho v balíku .tar.gz. Balík by měl obsahovat jediný adresář s názvem popisujícím vaše téma a jméno (např. drticka_virtualniho_odpadu_josef_novak/, v něm pak:

  • demo skript nebo README.demo — na nějakých mini testovacích datech ukažte, co program umí, případně vysvětlete, jak program rychle použít
  • testovací data k předchozímu, pokud jsou potřeba
  • program (nebo víc programů), který kromě dohodnuté funkcionality správně reaguje na standartní optiony
  • README — dokumentaci která popisuje co program jak dělá. Součástí dokumentance je “programátorská dokumentace” a.k.a. “internals” a.k.a. “hacking guide”, popis vnitřního rozložení programu do celků, poskytovaných interfaců a držených invariantů mezi nimi, a popis toku dat skrz program. Struktura P.D. se liší program od programu, ale obecné pravidlo je, že programátor s podobnou úrovní jako autor by z ní měl během cca 15 minut a) zjistit co a jak dělá každá součást kódu programu, b) být schopný v programu udělat malou rozumnou úpravu funkcionality a nerozbít to. Komentáře nemusí být (v extrémně přehledných případech) potřeba, ale většinou je vhodné kód pořádně popsat. Dobrý systém komentářů výrazně zjednodušuje programátorskou dokumentaci. Pokud se vám chce, README můžete formátovat jako manuálovou stránku, tj. ve formátu nroff/troff — podívejte se na jiné manuálové stránky do /usr/share/man.

Odevzdávání domácích úkolů

Stručný návod:

  1. Vytvořte si repozitář klikáním na GitHub nebo GitLab nebo případně na BitKyblík.
  2. Někde tam bude link na naklonování, použijte ho takhle: git clone https://github.com/neconeco/reporepo.git. Do odpovídajícího adresáře vám to stáhne obsah (prázdného) gitového repozitáře.
  3. Ve výsledném adresáři vyrobte domácí úkol, přidejte ho stejně jako na hodině (git add, git commit).
  4. Pomocí git push výsledek odešlete na github. Poprvé možná budete potřebovat něco složitějšího, asi jako git push -u origin master, program vás v případě potřeby upozorní sám. Detaily viz. git push --help.
  5. Mailem mi pošlete gitové URL, pomocí kterého si budu moct repozitář naklonovat (abych úkoly mohl zkontrolovat).
Pokud nemáte po ruce žádný unix/linux, repozitář si samozřejmě můžete naklonovat i když jste přihlášení přes SSH v labu a pracovat na něm jen přes SSH. Soubory jdou případně editovat i přes webové rozhraní GitHubu/GitLabu.

Běžné použití gitu je pěkně popsané tady.

Tutorial podobný tomu co jsme dělali na cvičení je tady.

Vizuální reference o tom co se vlastně děje při různých příkazech (doporučuju si aspoň projít obrázky!)

Pozn. Repozitáře nemusíte zakládat jako veřejné. Při nastavování všech možných správných přístupů pro neveřejné repozitáře se může hodit znát jméno mého účtu na GitHubu nebo můj SSH klíč. Případně, pokud máte repo veřejné a zároveň chcete mít možnost zabránit ostatním, aby Vaše řešení opisovali (což jim samozřejmě nepomůže, protože to poznám), můj PGP klíč je tady. Btw.: GitHub studentům poskytuje privátní repozitáře zadarmo.

Průběh cvičení

Věci co jsme vyrobili na cvičeních budou tady.

1 (22. 2. 2018)

Crash-course pozorování černého terminálu. Jak použít SSH.

Soubory, adresáře, cesty, koncept programu, ls, cd, cat, w, echo, rmidir, mkdir, rm, rm -r, cp -r, mv, ls -a, glob.

Editování souborů pomocí vi (používejte libovolný editor, ale vi byste měli umět použít alespoň jako notepad: vi soubor, [i], editování, [esc], :wq nebo :q!).

Stihli jsme si vyzkoušet >, < a >>.

Domácí úkol 1 (termín je prodloužený až na třetí cvičení): Zařiďte si gitový repozitář podle návodu nahoře, a pošlete mi na něj link (mailem). Ve svém repozitáři pak vyrobte adresář u01 a v něm prázdný soubor ahoj, obojí přidejte do správy verzí, commitněte a pošlete do repozitáře. Případně to na githubu/gitlabu můžete “naklikat” i přes webové rozhraní.

Bonusový domácí úkol: Uvařte si čaj nebo kafe a spusťte a projděte si vimtutor.

2 (29. 2. 2018)

Slepování programů pomocí |, jednoduché filtry: less, grep, wc, viděli jsme head, tail.

Jednoduché shellové skripty, sh, bash, #!, chmod +x.

Rychloúvod do správy verzí pomocí programu git.

: Napište skript, který pomocí fpc skompiluje pascalový zdrojový kód v souboru program.pas na program program. Výsledný program spustí, z jeho výstupu odstraní všechny řádky obsahující cokoliv jiného než čísla a mezery, a ze zbytku výstupu vypíše prvních 5 řádek. Po doběhnutí program i dočasný mezisoubor program.o smaže. Skript pojmenujte runpascal a uložte ho do svého repozitáře do adresáře u02.

3 (8. 3. 2018)
  • programování v shellu: proměnné a expanze, uvozovky vs. apostrofy, test, echo, read, if, while, for, &&, ||, exit, shift
  • regexy

: (termín: cvičení 5) Napište skript getmedia, který ze souboru s HTML stránkou vypíše adresy všech odkazů na multimédia, podle volby uživatele buď na obrázky nebo na zvuky. Obrázky se poznají tak, že URL končí příponou .jpg, .png nebo .svg. Zvuky jsou .wav, .mp3 a .ogg. Uživatel program zavolá buď jako ./getmedia --help, což mu vypíše krátkou nápovědu, nebo ./getmedia nejakysoubor.html, což ze souboru vytáhne URL obrázků i zvuků. Pokud uživatel chce jen obrázky, použije navíc přepínač -i, pokud chce jen zvuky, použije -s (např.: amatérský ornitolog program může použít jako ./getmedia -s zvuky_kukačky_kohoutí.html). URL se na výstupu vypíšou každé na samostatný řádek. Program umístěte do adresáře u03 ve vašich repozitářích.

4 (15. 3. 2018)
  • zbytek programování v shellu: read, for, seq, `backticky`, exit, funkce
  • začneme s tabulkovým DSL: tr, cut, sort, uniq
  • regexy ve vi

: (termín: cvičení 6) Stáhněte si soubor s MP3 přehrávači z cvičení (link viz. “Věci co jsme vyrobili na cvičeních” výše). Data jsou v souboru data/data5.csv (na hodině, tj. v adresáři 04/ jsme z něj odbourali hlavičku).

Část 1: Vyrobte skript colnumbers, který vypíše očíslované názvy sloupců, každý na jeden řádek.

Část 2: Pomocí prvního programu najděte číslo sloupce, ve kterém je uvedená hmotnost (může se hodit: cat -n). Vyrobte skript avgweight, který spočítá průměrnou hmotnost všech přehrávačů. Hint: Použijte aritmetickou expanzi $((...)) a while read. Počítejte jen s celou částí čísel — případnou desetinnou tečku (a všechno ostatní co nevypadá číselně) prostě zahoďte. Výsledek může být ořezaný na celé číslo. Přehrávače, u kterých data chybí, ignorujte.

Oba skripty by měly jako jediný parametr přijímat název souboru, ze kterého budou číst CSV data. Uložte je do vašeho gitu do adresáře u04.

5 (22. 3. 2018)
  • víc regexů ve vimu a náhled na sed
  • jak úspěšně použít vi jako excel
  • zbytek tabulkového DSL: paste, comm, náhled na join

Seznam věcí, co budeme dělat na cvičení:

  • z /etc/passwd vypište uživatele s nejvyšším UID
  • vypište seznam uživatelů, každého na jeden řádek, ve tvaru uid, jméno, skupina (zkuste to pomocí sed a paste)
  • to samé ve tvaru jméno uživatele, jméno skupiny
  • zjistěte seznam uživatelů, kteří nemají stejně pojmenovanou skupinu
    • pomocí comm
    • pomocí grep
  • Máte 2 adresáře. Napište skript, který najde soubory, které jsou v prvním adresáři, ale nejsou v druhém.
    • varianta: najděte soubory, které jsou v obou
    • varianta 2: včetně podsouborů a podadresářů
  • vypište seznam souborů z adresáře ve tvaru jméno [tab] přesná velikost v bajtech
  • stáhněte si gitový repozitář s výsledky cvičení, v adresáři data jsou soubory ip-by-country.csv, countrycodes_en.csv a kodyzemi_cz.csv (děkujeme za ně Petrovi Kučerovi)
    • soubory si připravte pro zpracování (např. odstraňte uvozovky a na oddělení sloupců použijte taby)
    • najděte země, které se česky jmenují stejně jako anglicky
    • vyrobte variantu ip-by-country.csv, kde jsou názvy zemí česky
    • Setřiďte IP adresy sestupně
    • Setřiďte ip-by-country.csv podle IP adres sestupně

: (termín: cvičení 7) Vyrobte skript sortlength který anglický seznam zemí setřídí podle délky názvu země. Můžete počítat s tím, že původní seznam bude při spouštění skriptu ve stejném adresáři, jako skript. Skript odevzdejte gitem v adresáři u05.

6 (29. 3. 2018)
  • souboroviny: parametry ls, find, du, ln, stat, chmod, chown, tee, dd
  • date

Na cvičení:

  • najděte nejvetší soubor přímo v /etc
  • najděte největší soubor ve /var (i rekurzivně)
  • najděte největší adresář ve /var
  • najděte podadrešář /var, ve kterém jsou průměrně největší soubory (tj. největší poměr celková velikost vs. počet souborů)
    • v průběhu výpočtu do souboru filecounts logujte počty souborů v jednotlivých adresářích.
  • najděte nejnovější soubor/adresář v /etc
    • tosamé rekurzivně
  • vyrobte zálohu adresáře unix (tj. obsahu našeho gitu ze cvičení), pojmenovanou jako unix-datum-čas
    • zajistěte, že v záloze jsou správně okopírovaná i metadata souborů
    • v adresáři unix změňte jeden soubor a adresář znovu zazálohujte. Snažte se zálohovat úsporně: kopírujte jen změněné soubory.

: Napište skript, který všechny soubory v adresáři (i rekurzivně), které mají název ALL_CAPSEM přepíše na malá písmena, ale soubory s MixedCaps názvem nechá být. Při kolizi názvů nic nedělejte, jen vypište chybovou hlášku na chybový výstup (echo ... >&2). Skript musí akceptovat volitelný option -r který přejmenovávání obrátí (smallcaps na ALLCAPS). Pokud se na příkazovém řádku nevyskytuje žádný další argument, skript přepíše aktuální adresář. Jiné další argumenty než -r skript interpretuje jako adresáře, které má předělat.

  • Pozor na soubory s mezerou a pomlčkami v názvu! (používejte uvozovky)
  • Na pořadí argumentů by nemělo záležet! (použijte shift)
  • Může se hodit: funkce se v shellu chovají jako skripty (včetně parametrů ve tvaru $1), definují se takhle: jmenofunkce () { příkazy; }

Skript pojmenujte capsmod a uložte ho do adresáře u06 ve vašich repozitářích.

7 (5. 4. 2018)
  • ssh, scp, rsync
  • archivy: tar, gzip, bzip2
  • xargs
  • split

Zábava na cvičení:

  • vyrobte si link na soubor /etc/passwd do svého domácího adresáře
  • přihlašte se pomocí ssh na počítač u-pl11.ms.mff.cuni.cz, v /tmp vyrobte soubor (pojmenujte ho nějak rozumně svým jménem), který ostatní můžou přečíst ale nemůžou ho přepsat. Vyzkoušejte si, že ostatním soubor opravdu přepsat nejde.
    • Vyrobte soubor, ze kterého nemůžou ani číst. Jak to zařídit tak, aby byl soubor už v okamžiku vyrobení chráněný?
    • Jde vyrobit skript, který uživatel nesmí přečíst, ale může ho spustit?
  • Jaký je rozdíl mezi eXecutable a Read bitem pro adresáře?
  • vyrobte 1MB soubor s náhodným obsahem
  • vyrobte zálohu adresáře unix (tj. obsahu našeho gitu ze cvičení), pojmenovanou jako unix-datum-čas
    • zajistěte, že v záloze jsou správně okopírovaná i metadata souborů
    • zálohu archivujte do souboru .tar
      • vyrobte ji tarem
      • zazipujte ji gzipem
      • vyrobte tarem přímo .tar.gz
      • vyzkoušejte si i .tar.bz2 a porovnejte velikost
    • zálohu přesuňte do /tmp adresáře na nějaký vzdálený počítač

: csplit je jako split, ale soubory rozděluje podle obsahu řádků (a ne binárně na stejně velké věci). Vyrobte skript splitpatch, který dostane 2 parametry: název souboru s patchem a název adresáře, do kterého má patch rozdělit na hromadu dílčích patchů tak, aby v každém výsledném souboru byly jen rozdíly jedné dvojice odpovídajících porovnaných souborů. “Patchem” rozumíme výstup z diff -ur nebo git diff. Příklad patche najdete v gitovém repozitáři cvičení v data/ccr.patch. Výsledné soubory by měly být všechny přímo v adresáři, který zadá uživatel, a pojmenované nějak podobně (lidsky rozeznatelně) jako odpovídající soubory. Lomítka oddělující názvy případných podadresářů mahraďte pomlčkou.

Výsledné soubory po rozdělení příkladu se můžou jmenovat např.: .gitignore.patch, README.md.patch, man-ccr.1.patch nebo src-actions.cpp.patch.

Skript tradičně uložte do gitu do u07/splitpatch).

Řešení úkolu 6 je na gitu.

8 (12. 4. 2018)

Zrušeno.

9 (19. 4. 2018)

make — jak automatizovat a paralelizovat vykonávání složitých procesů. Pravidla all a clean, patterny na pravidla, proměnné v make. Aplikace na stavění programů a dlouhé výpočty. Parametr -j, hodí se i -C a -f. Trik s nekompletním výsledkem a mv.

DÚ: (termín: cvičení 11) Napište Makefile na masové zpracování obrázků pro webovou galerii. V aktuálním adresáři bude kromě Makefile i hromada fotek ve formátu JPEG, s příponou .jpg. Spuštění make by mělo vyrobit zmenšenou kopii každého obrázku s příponou .thumb.jpg a velikostí maximálně 100×100 pixlů (použijte utilitu convert, v manuálu je kdyžtak odkaz na příklady). Ze zmenšených obrázků pak Makefile vyrobí ošklivé webové album v souboru index.html, ve kterém budou fotky zobrazené jako malé náhledy, a půjdou “rozkliknout” pro zobrazení původního obrázku.

Makefile by měl podporovat standardní targety all a clean.

Příklad výsledného HTML:

<html><body>
<a href="obr1.jpg"><img src="obr1.thumb.jpg"></a>
<a href="obr2.jpg"><img src="obr2.thumb.jpg"></a>
</body></html>

Na generování HTML použijte např. pomocný shellový skript. Makefile uložte tradičně do adresáře u09.

10 (26. 4. 2018)

sed a sedové pidiprogramy. Měli byste si zapamatovat minimálně příkazy s, d a y a matchování řádků pomocí čísla a regexu; hodí se i n a N a případně návěští : a goto b.

: (termín: cvičení 12) Vyrobte v sedu formátovač z plaintextu do HTML. V plaintextu (podobně jako v markdownu a TeXu) se odstavce rozdělují dvojitým enterem (a.k.a. prázdným řádkem), ve výsledku by tyto měly být ohraničeny tagy <p> a </p>. Odstavec, jehož prvním znakem je #, je považován za nadpis, ten by měl místo <p> být ohraničen tagy <h1> a </h1>. V textu zvýrazněte i jednotlivá slova (neobsahující mezeru nebo jiný bílý znak) která jsou “podtržená” ohraničením _podtržítky_, pomocí tagů <emph> a </emph>. Můžete počítat s tím, že soubor je ukončený prázdným řádkem.

Příklad: Plaintext:

# Varování
Dávejte _pozor_ na to,
aby stodola pěkně hořela.

...se přeloží například na následující HTML:

<h1>Varování</h1><p>Dávejte <emph>pozor</emph> na to, aby stodola pěkně hořela.</p>

Výsledek uložte jako spustitelný sedový skript plain2html (místo #!/bin/bash použijte #!/bin/sed -f) do adresáře u10.

11 (3. 5. 2018)

Poskládali jsme Uživatelsky Přívětivý Shellový Skript S Relativně Správným Parsováním Příkazové Řádky™ (R). Podobný interface prosím používejte na zápočťáky.

Koukli jsme se na procesy a poslali jsme signál.

: Vezměte domácí úkol 7 (splitpatch) a přidělejte do něj správné parsování příkazové řádky, jako na hodíně. Parametr -i určí vstupní patch (maximálně jeden — specifikace víc vstupů způsobí chybu; specifikace 0 vstupů způsobí načtení patche ze standardního vstupu). Parametr -d určí výstupní adresář (pokud není specifikovaný, vytvoří se na výstup adresář jméno_vstupního_patche.splitpatch/; pokud se vstup bere ze standardního vstupu a adresář není specifikovaný, program selže s rozumnou chybovou hláškou).

Výsledný upravený splitpatch uložte do adresáře u11.

12 (10. 5. 2018)

AWK

není.

13 (17. 5. 2018)

Nějaké praktické příklady.

: (poslední) Napište v awku skript na spojování záznamů podle klíče. Skript dostane 2 soubory pomocí awk -f skript soubor1 soubor2. V obou souborech jsou 2 sloupce oddělené tabem, první sloupec je klíč, druhý je hodnota. Klíče nejsou seřazené, a v každém souboru se každý klíč vyskytuje maximálně jednou. Na výstup vypište všechny dvojice hodnot, které v obou souborech mají stejný klíč. Skript nazvěte join2.awk a uložte do adresáře u12.

Bonusy

  • Sed je T-kompletní (tzn. “jde v něm naprogramovat všechno”). Důkazů je hodně, ale tenhle rozhodně bude nejohyzdnější. Jen v sedu (přehazováním textu za pomoci regulárních výrazů) jde napsat třeba arkanoid nebo kalkulačka s neomezenou přesností . Jestli to je rozumné se neví.
  • The Art Of UNIX Programming (online verze). Překvapivě stále více než aktuální. Trochu filozofické. Obsahuje odpovědi na většinu položitelných otázek začínajících na “Proč se v UNIXu proboha ….?” a užitečný náhled do historie a evoluce současného počítačového světa.
Jak se připojit do labu z domova?

Z unixu: ssh LOGIN@u-pl0.ms.mff.cuni.cz. Místo LOGIN napíšete své uživatelské jméno, na heslo se vás to zeptá.

Z windows: Stáhněte si Putty. Spusťte ji, do “Host name” napište u-pl0.ms.mff.cuni.cz. Na uživatelské jméno a heslo se to zeptá samo při připojování.

Z mobilu: droid, jablko

Místo u-pl0 můžete použít i jiná čísla počítačů: u-pl1, u-pl2 až cca. u-pl23.