Cvičení: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.
Cílem tohoto cvičení je představit vám klienta Gitu na příkazové řádce a také jak psát znovupoužitelné skripty.
Nezapomeňte, že Čtení před cvičením je povinné a je z něj kvíz, který musíte vyplnit před cvičením.
Skripty
Vraťme se zpět k prvnímu příkladu ze čtení před cvičením.
cat /proc/cpuinfo
cat /proc/meminfo
Uložíme-li text do souboru first.sh
, můžeme jej spustit následujícím
příkazem:
bash first.sh
Už ale také víte o shebangu, takže soubor upravíme a označíme jako spustitelný.
#!/bin/bash
cat /proc/cpuinfo
cat /proc/meminfo
Pro označení za spustitelný použijeme následující příkaz:
chmod +x first.sh
Teď můžeme skript spustit takto:
./first.sh
Nabízí se otázka: proč to přebytečné ./
? Vždyť se tím odkazujeme na
aktuální adresář (viz předchozí přednáška)?
Když použijeme příkaz (např. cat
), shell se podívá do tzv. cesty,
která je uložená v proměnné $PATH, aby našel soubor s tímto
programem. Na rozdíl od jiných operačních systémů se shell nedívá do
pracovního adresáře, když program nenajde v $PATH.
Pro spuštění programu v aktuálním adresáři proto musíme specifikovat i jeho
cestu. Naštěstí nemusí být absolutní, ale stačí relativní. Proto ten magický
zápis ./
.
Přesuneme-li se do jiného adresáře, můžeme program také spustit pomocí
relativní cesty, např. ../first.sh
.
Spusťte teď ls
v aktuálním adresáři. Měli byste vidět soubor first.sh
vypsaný zeleně. Pokud ne, zkuste ls --color
nebo ověřte, že jste správně
spustili chmod
.
Nemáte-li barevný terminál (neobvyklé, ale pořád možné), můžete použít ls -F
na odlišení typů souborů: adresáře pak budou končit lomítkem,
spustitelné soubory hvězdičkou.
Změna pracovního adresáře
Trochu program upravíme.
cd /proc
cat cpuinfo
cat meminfo
Spusťte skript znova.
Všimněte si, že navzdory tomu, že skript změnil adresář na /proc
, jsme po
jeho ukončení stále v původním adresáři.
Zkuste vložit pwd
na ověření, že skript je opravdu uvnitř /proc
.
Je důležité si odnést, že každý proces (běžící program; vč. skriptů) má svůj vlastní pracovní adresář. Po spuštění zdědí adresář od toho, kdo jej zavolal (např. shellu, v němž byl spuštěn). Následné změny adresáře ale nijak neovlivní ostatní procesy, takže je po ukončení volající stále ve stejném adresáři.
Ladění skriptů
Chcete-li vidět, co se děje, spusťte skript pomocí sh -x first.sh
. Zkuste si to. Pro delší skripty je ale lepší vypisovat vlastní
hlášky, protože -x
bývá příliš podrobné a je to spíš taková ladící
pomůcka.
Pro vypsání hlášky na terminál lze použít příkaz echo
. Až na pár
výjimek (více o nich později), jsou všechny jeho argumenty jen vypsány.
Vytvořte skript echos.sh
s následujícím obsahem a vysvětlete rozdíly:
echo alpha bravo charlie
echo alpha bravo charlie
echo "alpha bravo" charlie
Answer.
Argumenty na příkazové řádce
Argumenty příkazové řádky (jako například -l
pro ls
nebo -C
pro
hexdump
) jsou obvyklým způsobem, jak ovládat chování CLI nástrojů v
Linuxu. Pro nás, jako vývojáře, je důležité naučit se, jak s nimi uvnitř
našich programů pracovat.
O práci s argumenty v shellových skriptech budeme mluvit později, dnes si ukážeme jejich použití v Pythonu.
Přístup k těmto argumentům v Pythonu je jednoduchý. Potřebujeme do programu
přidat import sys
a poté k nim můžeme přistupovat přes seznam sys.argv
.
Následující program tedy vypíše své argumenty.
#!/usr/bin/env python3
import sys
def main():
for arg in sys.argv:
print("'{}'".format(arg))
if __name__ == '__main__':
main()
Při jeho spuštění (samozřejmě poté, co na něj zavoláme chmod +x
) uvidíme
následující (řádky prefixované $
značí příkaz, zbytek je jeho výstup).
$ ./args.py
'./args.py'
$ ./args.py one two
'./args.py'
'one'
'two'
$ ./args.py "one two"
'./args.py'
'one two'
Všimněme si, že nultá položka představuje vlastní název příkazu (ten teď nevyužijeme, ale může být užitečný pro některé chytré triky) a také jak se volání druhého a třetího příkazu liší uvnitř Pythonu.
To by nás ale nemělo překvapit, vzpomeňme si na předchozí cvičení a práci se jmény souborů s mezerami.
Jiné interpretry
Teď si vyzkoušíme, které interpretry můžeme dát do shebangu.
Vytvořte absolutní (!) cestu (nápověda: man 1 realpath
) k args.py
,
který jsme používali výše.
Použijte ji jako shebang v jinak prázdném souboru (např. use-args
) a označte jej jako spustitelný.
Hint.
Poté jej spusťte takto:
./use-args
./use-args first second
Zjistíte, že argument nula teď obsahuje cestu k vašemu skriptu, argument na
pozici jedna obsahuje vnější skript – use-args
a až za nimi jsou vlastní
argumenty z příkazové řádky (first
a second
).
Tohle je zásadní – když přidáme shebang, interpretr obdrží vstupní název souboru jako první argument. Jinými slovy – každý Linuxový interpretr musí začít vykonávat program, který dostane jako jméno souboru v prvním argumentu.
Přestože to může vypadat jako cvičení ve zbytečnostech, jde o demonstraci důležitého principu: Linux je extrémně nakloněn vytváření minijazyků. Potřebujete-li vytvořit interpretr pro svůj vlastní minijazyk, stačí jen zařídit, aby přijímal vstupní jméno souboru jako první argument a voilà, uživatelé v něm můžou psát své vlastní spustitelné soubory.
Jako další příklad si připravte následující soubor, uložte jej jako
experiment
(bez přípony) a označte jej jako spustitelný:
#!/bin/bash
echo Hello
Poznamenejme, že jsme se rozhodli znova úplně zahodit příponu, protože uživatele ve skutečnosti nezajímá jaký jazyk jsme použili. A ono je to stejně zachyceno pomocí shebangu.
Nyní změňte shebang na #!/bin/cat
a spusťte program znova.
Co se stalo?
Spusťte jej s nějakým argumentem (např. jako ./experiment experiment
).
Co se stalo?
Answer.
Změňte shebang na /bin/echo
. Co se stalo?
Git na příkazové řádce
Tato sekce popíše, jak používat Git na příkazové řádce namísto jeho grafické nástavby poskytované GitLabem. Motivaci k použití obojího jsme již popsali na předchozích cvičeních, tady ukážeme, jak přistupovat k souborům z příkazové řádky.
Přestože je možné upravovat soubory on-line v GitLabu, bývá mnohem jednodušší mít je lokálně a používat nějaký lepší editor (příp. IDE). Navíc, ne všechny nástroje mají své on-line protějšky a tak je budete muset spouštět lokálně.
Výběr editoru
Git bude často potřebovat spouštět váš editor, základem proto je zajistit, že použije ten, který jste si vybrali.
Následující kroky vysvětlíme podrobněji později, prozatím jen zajistěte, že
přidáte následující řádek na konec souboru ~/.bashrc
(mcedit
v něm
nahraďte za vámi vybraný editor):
export EDITOR=mcedit
Otevřete nový terminál a spusťte (včetně znaku dolaru):
$EDITOR ~/.bashrc
Pokud jste soubor upravili správně, měli byste jej opět vidět otevřený ve vašem oblíbeném textovém editoru.
Aby se změny projevily, je potřeba předem zavřít všechny terminály (tedy před použitím Gitových příkazů zmíněných níže).
Important: never use a graphical editor for $EDITOR
unless you
really know what you are doing. Git expects a certain behaviour from the
editor that is rarely satisfied by GUI editors but is always
provided by a TUI-based one.
Nastavení Gitu
Jedním z klíčových konceptů v Gitu je, že každý commit (změna) má autora – tedy je známo, kdo jej vytvořil. Podepisováni commitů zde přeskočíme a nebudeme tak uvažovat padělání/krádež identity.
Potřebujeme tedy Gitu říct, kdo jsme. Následující dva příkazy jsou absolutní minimum, co potřebujete spustit na počítači (nebo účtu), kde chcete pracovat s Gitem.
git config --global user.name "My real name"
git config --global user.email "my-email"
Přepínač --global
říká, že nastavení má být platné pro všechny Gitové
projekty. Pro lokální změnu můžete spustit stejný příkaz bez tohoto
přepínače uvnitř konkrétního projektu. To může být například užitečné pro
odlišení vaší soukromé a firemní identity.
Poznamenejme, že Git neověřuje správnost e-mailové adresy ani vašeho jména (stejně ani není, jak by mohl). Může zde být tedy cokoliv. Pokud ale použijete svou skutečnou e-mailovou adresu, GitLab dokáže spárovat commity s vaším účtem, atp., což může být užitečné.
Rozhodnutí je na vás.
První klonování (git clone
)
Pro následující příklad použijeme repozitář teaching/nswi177/2022/common/csv-templater.
Nejprve proveďte fork tohoto repozitáře do vlastního jmenného prostoru (v GitLabu přes prohlížeč). Hint.
Vytvoření forku projektu znamená vytvoření vaší vlastní kopie na GitLabu. Vytvořte fork – nepotřebujete k tomu přístup k zápisu do našeho repozitáře a také nechceme, abyste bojovali o stejné soubory.
Otevřete svůj fork projektu a klikněte na modré tlačítko Clone
. Měli byste
vidět adresy pro Klonování přes SSH a Klonování přes HTTPS.
Zkopírujte adresu HTTPS a použijte ji v příkazu clone
:
git clone https://gitlab.mff.cuni.cz/YOUR_LOGIN/csv-templater.git
Příkaz se vás zeptá na uživatelské jméno a heslo. Jako obvykle v našem GitLabu, použijte prosím přihlašovací údaje do SISu.
Některá prostředí můžou nabízet k použití tzv. klíčenky nebo podobné nástroje na ukládání přihlašovacích údajů. Klidně je používejte. Později se podíváme na to, jak používat SSH a asymetrickou kryptografii pro bezešvou práci s projekty Gitu bez potřeby starat se o uživatelská jména a hesla.
Nyní byste měli mít na svém počítači adresář csv-templater
.
Přesuňte se do něj a podívejte se, jaké soubory tam jsou.
A co skryté soubory?
Answer.
Neřekneme-li jinak, všechny příkazy budeme vykonávat uvnitř adresáře
csv-templater
.
Provedení změny (git status
a git diff
)
Opravte překlepy na řádku 11 ve skriptu Pythonu a v souboru README.md
a
spusťte git status
před i po změnách. Pozorně si přečtěte celý výstup
tohoto příkazu, abyste pochopili, co hlásí.
Vytvořte nový soubor demo/people.csv
s aspoň třemi sloupci a 4 řádky. Opět
ověřte, jak git status
hlásí tuto změnu v adresáři vašeho projektu.
Co jste se naučili? Answer.
Spusťte git diff
pro zobrazení toho, jak Git sleduje provedené změny. Proč
je tento výstup vhodný pro změny zdrojových kódů?
Příkaz git diff
je taky extrémně užitečný pro ověření, že provedené změny
jsou správné, tím že se zaměřuje jen na kontext změn namísto celých souborů.
Uložení změny natrvalo (git add
a git commit
)
Teď se připravte na svůj první commit (pro připomenutí: commit je v podstatě
verze, přip. pojmenovaný stav projektu) – spusťte git add csv_templater.py
. O soubor README.md
se postaráme později.
Jak to změnilo výstup git stutus
?
Answer.
Vytvořte svůj první commit pomocí git commit
. Nezapomeňte pro něj použít
výstižnou commit zprávu!
Poznamenejme, že bez přepínačů git commit
otevře váš textový
editor. Napište do něj commit zprávu, uložte a editor zavřete. Váš první
commit je tímto dokončen.
Pro krátké commit zprávy můžete použít git commit -m "Typo fix"
, kde celá
commit zpráva je dána argumentem přepínače -m
(všimněte si uvozovek kvůli
použití mezery).
Jak bude git status
vypadat teď? Zamyslete se nad tím před spuštěním
příkazu.
Odeslání změn na server
Nyní odešleme změny zpět do GitLabu použitím git push
. Příkaz se opět
zeptá na heslo a poté už byste měli vidět změny na GitLabu.
Které změny jsou na GitLabu? Answer.
Cvičení
Přidejte druhý překlep jako druhý commit z příkazové řádky.
Jako třetí commit přidejte políčko Date
do demo/call.txt
.
Pošlete změny do GitLabu. Všimněte si, že všechny commity byly poslány najednou.
Prohlížení commitů (git log
)
Prozkoumejte, co je v menu Repository -> Commits v GitLabu.
Porovnejte to s výstupem git log
a git log --oneline
.
Získání změn ze serveru
Změňte nadpis v README.md
aby také obsahoval napsáno v Pythonu.
Tentokrát ale proveďte změnu na GitLabu.
Nezapomeňte nejdříve pushnout lokální commity.
Pro aktualizaci lokálního klonu projektu použijte git pull
.
Příkaz git pull
je opravdu mocný, dokáže začlenit změny, které vznikly v
podstatě ve stejnou dobu na GitLabu a ve vašem lokálním klonu. Porozumění
tomuto procesu ale vyžaduje také znalosti větví, což je mimo rámec tohoto
cvičení.
Prozatím si tak pamatujte nemíchat lokální změny s těmi v GitLabu (nebo na
jiném stroji) aniž byste vždy ukončili práci pomocí git push
a začali
pomocí git pull
.
Něco navíc
Příkaz git log
zobrazuje spoustu informací, obvykle nás ale zajímají jen
ty nejnovější. Použijeme je pro připomenutí, na čem jsme pracovali, atp.
Následující příkaz tak bude dávat větší smysl:
git log --max-count=20 --oneline
Je to ale delší a obtížně zapamatovatelné. Zkuste toto:
git config --global alias.ls 'log --max-count=20 --oneline'
To je ještě horší! S touto magii ale Git náhle začne rozpoznávat následující podpříkaz:
git ls
A to může ušetřit čas.
Naše oblíbené aliasy jsou pro následující příkazy.
st = status
ci = commit
ll = log --format='tformat:%C(yellow)%h%Creset %an (%cr) %C(yellow)%s%Creset' --max-count=20 --first-parent
Zkuste si je nejprve spustit před přidáním do svého Gitu.
Spouštění testů lokálně
Protože už víte, co jsou shebang, executable bit, a skripty obecně, máte dostatek znalostí, abyste spustili naše testy lokálně bez potřeby GitLabu.
Mělo by to učinit váš vývoj rychlejší a přirozenější, když nebudete muset čekat na GitLab.
Jednoduše spusťte ./bin/run_tests.sh
v kořenovém adresáři vašeho projektu
a prohlédněte si výsledky.
Můžete také spustit jen konkrétní podmnožinu testů.
./bin/run_tests.sh tasks/01/factor
./bin/run_tests.sh tasks/01
./bin/run_tests.sh quizzes/02/before
Poznámka: Používate-li vlastní instalaci Linuxu, může být potřeba předem
nainstalovat balíček bats
.
Hodnocené úlohy (deadline: 13. březen)
Počínaje těmito úlohami, nezapomeňte označovat vaše skripty jako spustitelné a vždy přidávat správný shebang. Budou na to speciální testy.
Použití Git CLI (20 bodů)
Použijte git config
na dočasnou změnu svého e-mailu na
VAS_GITLAB_LOGIN@nswi177.gitlab.mff.cuni.cz
(samozřejmě VAS_GITLAB_LOGIN
nahraďte tím správným) a udělejte s tímto e-mailem jeden commit do svého
repozitáře s hodnocenými úlohami. Můžete třeba vytvořit nový soubor
03/git_cli.txt
, nevíte-li, co změnit ;-).
Aktualizace: Tento úkol je kontrolován na GitLab CI. Nicméně, GitLabové testy mohou najednou začít selhávat (tj., nejdříve jsou testy v pořádku a najednou jsou špatně až po několika commitech). GitLab si totiž nenaklonuje celou historii projektu, když spouští pipeline (takže vidí jen posledních pár commitů). My to pak budeme kontrolovat na celé historii, takže to hodnocení neovlivní.
Jinými slovy: pokud tato úloha někdy na GitLabu prošla testy a začala z ničeho nic selhávat někdy později, je to v pořádku.
03/tree.py
(30 bodů)
Upravte svůj skript 02/tree.py
, aby přijímal jako argument jméno adresáře
k vypsání. Není-li žádný argument zadán, měl by stále vypisovat aktuální
adresář.
Také přidejte podporu pro přepínač -d
, který způsobí vypisování pouze
adresářů. Přepínač může být před adresářem k vypsání nebo za ním nebo se
může vyskytovat samostatně při vypisování aktuálního adresáře.
03/factor.py
(20 bodů)
Přepracujte svůj skript z prvního cvičení, aby načítal číslo jako argument příkazového řádku.
03/architecture.sh
(10 bodů)
Aktualizujte skript z předchozího cvičení, aby měl správný shebang a nastavený executable bit.
03/git.txt
(20 bodů)
Budete potřebovat následující repozitář.
https://d3s.mff.cuni.cz/f/teaching/nswi177/202122/labs/task-03.git/
Repozitář obsahuje více souborů. Zkopírujte ten, který je zmíněný v commit
message do 03/git.txt
.
Jinými slovy, naklonujte si výše zmíněný repozitář, prohlédněte si
existující commity a v jejich textech najdete jméno souboru, který máte
zkopírovat do vašeho projektu (jako 03/git.txt
).
Automatické testy ověřují jen přítomnost souboru, ne jestli jste zkopírovali ten správný.
Učební výstupy
Znalosti konceptů
Znalost konceptů znamená, že rozumíte významu a kontextu daného tématu a jste schopni témata zasadit do většího rámce. Takže, jste schopni …
-
vysvětlit, co znamená skript (v kontextu Linuxového prostředí)
-
vysvětlit, co jsou argumenty příkazové řádky
-
vysvětlit, co je to shebang a executable bit a jak ovlivní spuštění skriptu
-
vysvětlit, jak jsou argumenty (parametry) předané skriptu s shebangem
-
vysvětlit, co je pracovní kopii Gitu (klon)
Praktické dovednosti
Praktické dovednosti se obvykle týkají použití daných programů pro vyřešení různých úloh. Takže, dokážete …
-
vytvořit Linuxový skript se správným shebangem
-
nastavit executable bit skriptu
-
přistupovat k argumentům příkazové řádky z Pythoního skriptu
-
nastavit Git (jméno a e-mail)
-
naklonovat Gitový repozitář přes HTTPS
-
prohlédnout změny v Gitové pracovní kopii
-
vytvořit commit v Gitovém repozitáři
-
nahrát nové změny na Gitový server (např. GitLab) a stáhnout z něj aktualizace
-
prohlédnout si souhrnné informace o předchozích commitech
-
upravit si chování Gitu pomocí aliasů (volitelné)