U ovoj lekciji ćemo proći kroz nekoliko načina pomoću kojih možete da poboljšate vaš rad u korišćenju shell-a. Sa shell-om radimo već neko vrijeme, ali smo se najviše fokusirali na izvršavanje različitih komandi. Sada ćemo vidjeti kako da pokrenemo nekoliko procesa u isto vrijeme dok ih pratimo, kako da zaustavimo ili pauziramo specifični proces i kako da podesimo proces da radi u pozadini.
Takođe ćemo naučiti različite načine da poboljšate vaš shell i druge alate, definisanjem pseudonima i konfigurisanjem istih pomoću dotfiles. I jedno i drugo će vam uštedjeti vrijeme, npr. korišćenjem istih konfiguracija za sve vaše mašine bez potrebe da pišete duge komande. Vidjećemo i kako da radimo sa udaljenim mašinama koristeći SSH.
Kontrola posla
U nekim slučajevima ćete morati da prekinete posao u toku izvršavanja, npr. ukoliko je komandi potrebno previše vremena da bi se izvršila (kao npr.
1
nalaženje
1
Ctrl-C
Ubijanje procesa
Vaš shell koristi UNIX komunikacioni mehanizam koji se zove signal za prosleđivanje informacija procesu. Kada proces primi signal, on zaustavlja svoje izvršavanje, bavi se signalom i potencijalno mijenja tok izvršenja na osnovu informacija koje je signal isporučio. Iz ovih razloga, signali su ono što zaustavlja softver.
U našem slučaju, kada kucamo
1
Ctrl-C
1
SIGINT
Evo minimalističkog primjera Python programa koji snimi
1
SIGINT
1
SIGQUIT
1
Ctrl-\
1 2 3 4 5 6 7 8 9 10 11 12
#!/usr/bin/env python import signal, time def handler(signum, time): print("\nI got a SIGINT, but I am not stopping") signal.signal(signal.SIGINT, handler) i = 0 while True: time.sleep(.1) print("\r{}".format(i), end="") i += 1
Evo šta se dešava ukoliko unesemo
1
SIGINT
1
SIGQUIT
1
^
1
Ctrl
1 2 3 4 5 6
$ python sigint.py 24^C I got a SIGINT, but I am not stopping 26^C I got a SIGINT, but I am not stopping 30^\[1] 39913 quit python sigint.py
Dok su
1
SIGINT
1
SIGQUIT
1
SIGTERM
1
kill -TERM <PID>
Pauziranje i stavljanje procesa u pozadinu
Signali mogu raditi i druge stvari mimo zaustavljanja procesa. Na primer,
1
SIGSTOP
1
Ctrl-Z
1
SIGTSTP
1
SIGSTOP
Zatim možemo nastaviti pauzirani posao koji se nalazi u prvom planu ili u pozadini koristeći, zavisno od toga, fg ili bg.
Jobs komanda izlistava nezavršene poslove koji su povezani sa trenutnom sesijom terminala. Možete referencirati te poslove koristeći njihov pid (možete koristiti pgrep da to saznate). Još više intuitivnije, možete referencirati proces koristeći simbol procenta i njegov broj zadatka (prikazan kao
1
jobs
1
$!
Dodatna stvar koju je potrebno znati jeste da
1
&
Da bi prebacili u pozadinu program koji je u toku možete odraditi
1
Ctrl-Z
1
bg
1
SIGHUP
1
SIGHUP
1
disown
Ispod je jednostavna sesija koja prikazuje neke od tih koncepata.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
$ sleep 1000 ^Z [1] + 18653 suspended sleep 1000 $ nohup sleep 2000 & [2] 18745 appending output to nohup.out $ jobs [1] + suspended sleep 1000 [2] - running nohup sleep 2000 $ bg %1 [1] - 18653 continued sleep 1000 $ jobs [1] - running sleep 1000 [2] + running nohup sleep 2000 $ kill -STOP %1 [1] + 18653 suspended (signal) sleep 1000 $ jobs [1] + suspended (signal) sleep 1000 [2] - running nohup sleep 2000 $ kill -SIGHUP %1 [1] + 18653 hangup sleep 1000 $ jobs [2] + running nohup sleep 2000 $ kill -SIGHUP %2 $ jobs [2] + running nohup sleep 2000 $ kill %2 [2] + 18745 terminated nohup sleep 2000 $ jobs
Specijalni signal je
1
SIGKILL
Možete naučiti više o ovim i drugim signalima ovdje ili kucanjem man signal ili
1
kill -t
Multiplexeri Terminala
Kada koristite interfejs komandne linije obično ćete željeti da pokrenete više stvari odjednom. Na primer, možda ćete željeti da pokrenete vaš editor i vaš program jedno pored drugog. Iako ovo može biti ostvareno otvaranjem novog prozora terminala, korišćenje multiplexera terminala je svestranije rešenje.
Multiplexeri terminala kao što je tmux vam pružaju mogućnost multiplexa terminala prozora koristeći panes i tabove tako da možete imati interakciju sa više shell sesija. Još više, multiplexeri terminala vam dopuštaju da odvojite trenutnu sesiju terminala i da se prikačite na nju u nekom kasnijem trenutku. Ovo može mnogo popraviti vaše iskustvo kada radite sa udaljenim mašinama jer izbjegava upotrebu
1
nohup
Najpopularniji multiplexer terminala ovih dana je tmux.
1
tmux
1
tmux
1
<C-b> x
1
Ctrl+b
1
Ctrl+b
1
x
1
tmux
- Sesije - Sesija je nezavisni radni prostor sa jednim ili više prozora
- započinje novu sesiju
1
tmux
- je započinje sa tim nazivom
1
tmux new -s NAME
- izlistava trenutnu sesiju
1
tmux ls
- U okviru kucanje
1
tmux
odvaja trenutnu sesiju1
<C-b> d
- pridodaje poslednju sesiju. Možete da koristite
1
tmux a
flag da označite koju1
-t
- Windows - Ekvivalent tabovima u editoru ili pretraživaču - vizuelno odvaja dio iste sesije
- Kreira novi prozor. Da ga zatvorite možete zaustaviti shell koristeći
1
<C-b> c
1
<C-d>
- Ide do N th prozora. Imajte u vidu da su numerisani
1
<C-b> N
- Ide do prethodnog prozora
1
<C-b> p
- Ide do sledećeg prozora
1
<C-b> n
- Mijenja ime trenutnog prozora
1
<C-b> ,
- Izlistava trenutni prozor
1
<C-b> w
- Panes - Kao i vim splits, panes vam dopuštaju da imate više shell-ova na istom displeju.
- Dijeli trenutni pane horizontalno
1
<C-b> "
- Dijeli trenutni pane vertikalno
1
<C-b> %
- pomjera pane u zadati pravac. Pravac ovdje označava tastere sa strelicama.
1
<C-b> <direction>
- Uključuje zoom za trenutni pane
1
<C-b> z
- Započinje pomicanje unazad. Zatim možete pritisnuti
1
<C-b> [
da započnete selekciju i1
<space>
da kopirate tu selekciju.1
<enter>
- Kruži kroz pane uređenje.
1
<C-b> <space>
Za dalje čitanje, ovdje je kratki tutorijal na
1
tmux
1
screen
Pseudonimi
Može biti zamorno kucanje dugih komandi koje uključuju mnoge flagove ili opširne opcije. Iz ovog razloga, većina shell-ova podržava pseudonime. Shell pseudonim je kratka forma neke komande koju će vaš shell automatski zamijeniti za vas. Na primer, psuedonim u bash-u ima sledeću strukturu:
1
alias alias_name="command_to_alias arg1 arg2"
Imajte u vidu da nema razmaka okolo znaka jednako
1
=
Pseudonimi imaju mnoge pogodne funkcije:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
# Make shorthands for common flags alias ll="ls -lh" # Save a lot of typing for common commands alias gs="git status" alias gc="git commit" alias v="vim" # Save you from mistyping alias sl=ls # Overwrite existing commands for better defaults alias mv="mv -i" # -i prompts before overwrite alias mkdir="mkdir -p" # -p make parent dirs as needed alias df="df -h" # -h prints human readable format # Alias can be composed alias la="ls -A" alias lla="la -l" # To ignore an alias run it prepended with \ \ls # Or disable an alias altogether with unalias unalias la # To get an alias definition just call it with alias alias ll # Will print ll='ls -lh'
Imajte u vidu da pseudonimi nisu trajni u shell sesiji po default-u. Da bi neki pseudonim bio trajan morate ih uključiti u shell startup datoteci, kao što je
1
.bashrc
1
.zshrc
Dotfiles
Mnogi programi se podešavaju koristeći datoteke sa čistim tekstom poznate kao dotfiles (jer naziv datoteke počinje sa
1
.
1
~/.vimrc
1
ls
Shell-ovi su jedan primjer programa koji se podešavaju preko takvih fajlova. Prilikom pokretanja, vaš shell će pročitati mnoge datoteke da bi se učitala njegova podešavanja. Zavisno od shell-a, bilo da pokrećete login i/ili interakciju, čitav proces može biti veoma kompleksan. Ovo je odličan resurs na ovu temu.
Za
1
bash
1
.bashrc
1
.bash_profile
1
PATH
1
export PATH="$PATH:/path/to/program/bin"
Neki drugi primjeri alata koji mogu biti podešeni kroz dotfiles su:
1
bash - ~/.bashrc, ~/.bash_profile
1
git - ~/.gitconfig
- -
1
vim
and the1
~/.vimrc
1
~/.vim folder
1
ssh - ~/.ssh/config
1
tmux - ~/.tmux.conf
Kako da organizujete vaše dotfiles? Oni bi trebali da budu u njihovom posebnom folderu, ispod kontrole verzije, i symlinked na mjesto koristeći script. Ovo ima sledeće benefite:
- Laka instalacija: ukoliko se ulogujete na novu mašinu, potvrđivanje vaših podešavanja će trajati samo oko minut.
- Prenosivost: Vaši alati će raditi na isti način svuda.
- Sinhronizacija: Možete da ažurirate vaše dotfiles bilo gdje i da svi oni budu sinhronizovani.
- Praćenje promjena: Vjerovatno ćete kroz vašu čitavu programersku karijeru održavati vaše dotfiles, i jako je dobro imati kontrolu istorije za projekte koji će duže trajati.
Šta bi trebali da stavite u dotfiles? Možete učiti o podešavanju vaših alata čitanjem online dokumentacije ili man pages. Drugi dobar način jeste pretraživanje interneta za blog postove o specifičnim programima, gdje će vam autori iznijeti njihove preference podešavanja. Još jedan način da učite o podešavanjima jeste pregledanjem dotfiles drugih ljudi: možete pronaći gomilu dotfiles repositories na Githubu - pogledajte najpopularnije ovdje (Savjetujemo vam da ne kopirate na slijepo podešavanja). Ovdje je još jedan dobar resurs na ovu temu.
Svi instruktori ovih lekcija imaju njihove dotfiles koji su svima dostupni na Github-u: Anish, Jon, Jose.
Prenosivost
Čest problem sa dotfiles jeste što podešavanja možda neće raditi u radu sa nekoliko mašina, npr. ukoliko imaju različite operativne sisteme ili shell-ove. Ponekad takođe želite da se podešavanja primjenjuju samo na mašini na kojoj u tom trenutku radite.
Postoje česti trikovi da vam to olakšaju. Ukoliko to datoteka sa podešavanjima podržava, koristite ekvivalent if izjava da bi na mašini primjenili specifična podešavanja. Na primer, vaš shell može imati nešto kao što je:
1 2 3 4 5 6 7
if [[ "$(uname)" == "Linux" ]]; then {do_something}; fi # Check before using shell-specific features if [[ "$SHELL" == "zsh" ]]; then {do_something}; fi # You can also make it machine-specific if [[ "$(hostname)" == "myServer" ]]; then {do_something}; fi
Ukoliko fajl sa podešavanjima to podržava, koristite includes. Na primer,
1
~/.gitconfig
1 2
[include] path = ~/.gitconfig_local
Onda na svakoj mašini,
1
~/.gitconfig_local
Ova ideja je takođe korisna ako želite da različiti programi dijele ista podešavanja. Na primer, ukoliko želite da i
1
bash
1
zsh
1
.aliases
1 2 3 4
# Test if ~/.aliases exists and source it if [ -f ~/.aliases ]; then source ~/.aliases fi
Udaljene mašine
Kod programera je postalo često da koriste udaljene servere u njihovom svakodnevnom životu. Ukoliko morate da koristite udaljene servere da bi razvili backend software ili vam je potreban server sa visokim računarskim sposobnostima, na kraju ćete koristiti Secure Shell (SSH). Kao i za većinu alata koje smo prešli, SSH je veoma podesiv i vrijedan je učenja.
Da izvršite komandu
1
ssh
1
ssh [email protected]
Ovdje pokušavamo da ssh kao korisnik
1
foo
1
bar.mit.edu
1
bar.mit.edu
1
ssh bar
Izvršavanje komandi
Funkcija
1
ssh
1
ssh foobar@server ls
1
ls
1
ssh foobar@server ls | grep PATTERN
1
ls
1
ls | ssh foobar@server grep PATTERN
1
ls
SSH ključevi
Autentikacija na bazi ključeva koristi kriptografiju javnog ključa kako bi dokazala serveru da klijent posjeduje tajni privatni ključ bez otkrivanja ključa. Na ovaj način ne morate ponovo da unosite password svaki put. Ipak, privatni ključ (često kao
1
~/.ssh/id_rsa
1
~/.ssh/id_ed25519
Generisanje ključeva
Da bi generisali par možete izvršiti ssh-keygen.
1
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519
Trebali bi da izaberete lozinku, da bi izbjegli da neko ko dođe do vašeg privatnog ključa ima autorizovani pristup serverima. Koristite ssh-agent ili gpg-agent tako da ne morate da kucate vašu lozinku svaki put.
Ako ste ikada podešavali pushing na GitHub koristeći SSH ključ, onda ste vjerovatno napravili korake koji su navedeni ovdje i već imate validan par ključeva. Da bi provjerili da li imate lozinku i da je potvrdite možete izvršiti
1
ssh-keygen -y -f /path/to/key
Autentikacija bazirana na ključevima
1
ssh
1
.ssh/authorized_keys
1
cat .ssh/id_ed25519.pub | ssh foobar@remote 'cat >> ~/.ssh/authorized_keys'
Jednostavnije rešenje može biti postignuto sa
1
ssh-copy-id
1
ssh-copy-id -i .ssh/id_ed25519.pub foobar@remote
Kopiranje datoteka preko SSH-a
Postoji mnogo načina da kopirate datoteke preko SSH:
- , najlakše je koristiti
1
ssh+tee
izvršenje komande i STDIN input koristeći1
ssh
. Sjetite se da tee ispisuje output iz STDIN u datoteku.1
cat localfile | ssh remote_server tee serverfile
- scp kada kopirate veliku količinu datoteka/direktorijuma, sigurna copy komanda je pogodnija jer se lakše može kretati kroz paths. Sintaksa je
1
scp
.1
scp path/to/local_file remote_host:path/to/remote_file
- rsync je poboljšanje u odnosu na zbog detektovanja identičnih datoteka lokalno i udaljeno, i sprečavanja njihovog ponovnog kopiranja. Takođe omogućava bolju kontrolu nad symlinks, dozvolama i ima dodatne funkicje kao što su
1
scp
flag koji može nastaviti iz prethodno prekinute kopije.1
--partial
ima sličnu sintaksu kao i1
rsync
.1
scp
Prosleđivanje port-a
U mnogim scenarijima ćete naići na software koji sluša određene portove na mašini. Kada se ovo desi na vašoj lokalnoj mašini možete kucati
1
localhost:PORT
1
127.0.0.1:PORT
Ovo se naziva prosleđivanje port-a i dolazi u dvije varijatnte: Local Port Forwarding and Remote Port Forwarding (pogledajte slike za više detalja, slike su sa ovog StackOverflow posta.
Local Port Forwarding
Remote Port Forwarding
Najčešći scenario je local port forwarding, gdje service na udaljenoj mašini sluša port a vi želite da povežete port na lokalnoj mašini da biste ga proslijedili na udaljeni port. Na primer, ukoliko mi izvršimo
1
jupyter notebook
1
8888
1
9999
1
ssh -L 9999:localhost:8888 foobar@remote_server
1
locahost:9999
SSH podešavanja
Prošli smo mnoge argumente koje možemo da proslijedimo. Izazovna alternativa jeste da se kreira shell pseudonim koji izgleda ovako:
1
alias my_server="ssh -i ~/.id_ed25519 --port 2222 -L 9999:localhost:8888 foobar@remote_server
Ipak, postoji bolja alternativa koristeći
1
~/.ssh/config
1 2 3 4 5 6 7 8 9 10
Host vm User foobar HostName 172.16.174.141 Port 2222 IdentityFile ~/.ssh/id_ed25519 LocalForward 9999 localhost:8888 # Configs can also take wildcards Host *.mit.edu User foobaz
Dodatna prednost korišćenja
1
~/.ssh/config
1
scp
1
rsync
1
mosh
Imajte na umu da
1
~/.ssh/config
Konfiguracija na serveru je obično označena u
1
/etc/ssh/sshd_config
Ostalo
Čest problem prilikom povezivanja sa udaljenim serverom su prekidi veze zbog isključivanja/spavanja računara ili promjene mreže. Štaviše, može postati prilično frustrirajuće ukoliko neko ima značajan lag korišćenjem ssh-a. Mosh, mobilni shell, poboljšanje je u odnosu na ssh, omogućuje roming veze, povremeno povezivanje i pružanje inteligentnog lokalnog echo-a.
Ponekad je prikladno montirati ga u udaljenu datoteku. sshfs može montirati datoteku na udaljeni server lokalno, a zatim možete koristiti lokalni editor.
Shells & Frameworks
Tokom lekcije o shell alatima i scriptingu, prošli smo
1
bash
Na primer,
1
zsh
1
bash
- Pametniji globbing,
1
**
- Inline globbing/wildcard ekspanzija
- Pravopisna korekcija
- Bolje popunjavanje/odabir tabova
- Path ekspanzija (će se proširit kao
1
cd /u/lo/b
)1
/usr/local/bin
Frameworks mogu poboljšati shell takođe. Neki popularni opšti frameworks su prezto ili ohmyz, i manji koji se fokusiraju na specifične funkcije kao što su zsh-syntax-highlighting ili zsh-history-substring-search. Shell kao što je fish uključuje mnoge user-friendly funkcije defaultno. Neke od tih funkcija uključuju
- Pravi prompt
- Označavanje sintaksnih komandi
- Pretraga substring istorije
- Dovršavanje flagova na bazi manpage-a
- Pametnije auto dovršavanje
- Prompt teme
Treba da imate na umu da kada koristite ove frameworke, da oni mogu usporiti vaš shell, posebno ukoliko kod koji oni izvršavaju nije optimizovan ili se radi o previše koda. Uvijek ga možete profilisati ili omogućiti funkcije koje ne koristite često ili ih ne vrednujete u odnosu na brzinu.
Emulatori Terminala
Zajedno sa podešavanjem vašeg shella, vrijedi uložiti malo vremena da bi izabrali emulator terminala i njegova podešavanja. Postoji mnogo emulatora terminala (ovdje je poređenje
S obzirom na to da možete provoditi stotine ili hiljade sati u vašem terminalu, isplati se da pogledate njegova podešavanja. Neki od tih stvari koje bi željeli da podesite u vašem terminalu uključuju:
- Izbor fonta
- Schemu boja
- Prečice na tastaturi
- Tab/Pane podrška
- Scrollback podešavanja
- Performanse (Neki noviji terminali kao što su Alacritty, ili kitty nude ubrzanje GPU-a).
Vježbe
Kontrola poslova
-
Iz onoga što smo vidjeli, možemo koristiti neke
komande da dobijemo proces ID posla i zatim da ih ugasimo, ali postoji bolji način da to odradimo. Započnite1
ps aux | grep
posao u terminalu, prebacite ga u pozadinu sa1
sleep 10000
i nastavite izvršavanje sa1
Ctrl-Z
. Sada koristite pgrep da saznate ID procesa i pkill da bi ga ugasili bez toga da sami kucate ID procesa.(Nagovještaj: koristite1
bg
flag).1
-af
-
Recimo da ne želite da započnete proces dok se drugi ne završi, na koji način bi to riješili? U ovoj vježbi naš proces ograničavanja će uvijek biti
. Jedan način da ovo ostvarite jeste da koristite wait komandu. Pokušajte da pokrenete sleep komandu i da1
sleep 60 &
sačeka dok se proces u pozadini završi.1
ls
Ipak, ovakva strategija neće uspjeti ukoliko započnemo u drugoj bash sesiji, budući da
1
wait
1
kill
1
kill -0
1
pidwait
1
sleep
Multiplexeri Terminala
- Pratite ovaj tutorijal i naučite kako da uradite neka osnovna podešavanja prateći ove korake.
1
tmux
Pseudonimi
- Kreirajte pseudonim koji se pretvara u
1
dc
kada ga pogrešno napišete.1
cd
- Pokrenite da bi dobili vaših top 10 komandi koje najčešće koristite i razmislite da napišete kraće pseudonime za njih. Napomena: ovo radi za Bash; Ukoliko koristite ZSH, koristite
1
history | awk '{$1="";print substr($0,2)}' | sort | uniq -c | sort -n | tail -n 10
umjesto samo1
history 1
.1
history
Dotfiles
Hajde da vas ubrzamo sa dotfiles.
- Kreirajte folder za vaše dotfiles i postavite kontrolu verzije.
- Dodajte konfiguraciju za bar jedan folder, npr. vaš shell, sa nekim podešavanjem (za početak, može biti nešto tako jednostavno kao što je podešavanje vašeg shell prompta stavljajući ).
1
$PS1
- Podesite način za bržu instalaciju vaših dotfiles (i bez ručnog truda) na novoj mašini. Ovo može biti jednostavno kao shell skripta koja poziva za svaku datoteku, ili možete koristiti specijalno sredstvo.
1
ln -s
- Testirajte vašu instalacionu skriptu na svježoj virtualnoj mašini
- Prebacite sve svoje trenutne konfiguracije alata u skladište vaših dotfiles
- Objavite vaše dotfiles na GitHubu.
Udaljene mašine
Instalirajte Linux virtualnu mašinu (ili koristite već postojeću) za ovu vježbu. Ukoliko vam nisu poznate virtualne mašine pogledajte ovaj tutorijal da bi je instalirali.
- Idite na i provjerite da li imate par SSH ključeva tu. Ukoliko nemate, generišite ih sa
1
~/.ssh/
. Preporučuje se da koristite password i1
ssh-keygen -o -a 100 -t ed25519
, više informacija ovdje.1
ssh-agent
- Editujte da ima unos kakav slijedi
1
.ssh/config
1 2 3 4 5
Host vm User username_goes_here HostName ip_goes_here IdentityFile ~/.ssh/id_ed25519 LocalForward 9999 localhost:8888
- Koristite da bi kopirali vaš ssh ključ na serveru.
1
ssh-copy-id vm
- Pokrenite webserver na vašoj VM izvršavanjem . Pristupite VM webserveru krećući se do
1
python -m http.server 8888
u vašoj mašini.1
http://localhost:9999
- Uredite vaš SSH server config sa i onemogućite autentikaciju passworda editovanjem vrijednosti
1
sudo vim /etc/ssh/sshd_config
. Onemogućite root login uređivanjem vrijednosti1
PasswordAuthentication
. Restartujte1
PermitRootLogin
servise sa1
ssh
. Pokušajte ssh ponovo.1
sudo service sshd restart
- (Izazov) Instalirajte mosh u VM i uspostavite konekciju. Zatim prekinite konekciju network adaptera sa serverom/VM. Da li se mosh može propisno oporaviti od toga?
- (Izazov) Pogledajte šta i
1
-N
flagovi rade u1
-f
i smislite koju komandu da izvršite da bi postigli port forwarding u pozadini.1
ssh