Ten poradnik piszę w równym stopniu dla Was co dla siebie. Znajdziesz w nim opis kilku praktycznych poleceń przydatnych w codziennej pracy w Linuxie. Nie mam dobrej pamięci do składni i nazw poleceń więc na przestrzeni lat posługiwałem się rozmaitymi notatkami, plikami tekstowymi i dokumentami. Często odwiedzając Stack Overflow mam déjà vu, pewnie nie bez powodu. Wiele z najpopularniejszych odpowiedzi na pytania takie jak „jak skopiować plik przez SSH” czy „jak wyszukać tekst rekursywnie w całym folderze” odwiedzam regularnie co kilka miesięcy.
W tym artykule chciałbym stworzyć i podzielić się z Tobą swoim zestawem kilku przydatnych poleceń w Linuxie. Ja najczęściej korzystam z dystrybucji opartych o Debian (a więc Ubuntu oraz Mint). o ile korzystasz z innych dystrybucji możliwe iż niektóre z poleceń lub ścieżek plików systemowych będą u Ciebie wyglądały inaczej (na 100% te dotyczące zarządzania pakietami, a więc wszędzie tam gdzie ja używam apt-get)
Absolutne podstawy
Na starcie chciałbym wrzucić kilka zdecydowanie podstawowych poleceń. Robię to ponieważ sporo osób trafia na tą stronę szukając właśnie najważniejszych, podstawowych komend w Linuxie.
- pwd – wyświetla bieżący folder
- ls – wyświetla listę plików w folderze. Posiada wiele przydatnych parametrów, np. -l aby wyświetlić „tabelkę” ze szczegółowymi danymi czy -t aby posortować pliki po czasie modyfikacji. pozostało parametr -a który spowoduje wyświetlenie plików ukrytych. Tak jak w każdym poleceniu, parametry jednoliterowe można łączyć, a więc np. ls -alt
- cd – zmiana folderu.
- cd .. – przejście do folderu nadrzędnego.
- cd ~ – przejście do folderu domowego dla danego użytkownika
- ifconfig -a – wyświetla adresy IP interfejsów sieciowych Twojej maszyny. jeżeli chcesz sprawdzić adres publiczny możesz „zapytać” curl’em chociażby ifconfig.me (curl ifconfig.me)
- nano – chyba najwygodniejszy edytor tekstowy dla Linuxa, instalowany standardowo w większości dystrybujcji. Otwieramy plik poprzez nano nazwa_pliku
cdn…
Jak dodać alias (skrót) polecenia
Aliasy ułatwiają życie – pozwalają zapisać złożone polecenia pod przystępnym, krótkim skrótem. Mechanizm persystencji aliasów zależy od dystrybucji Linuksa oraz używanego shella. Ja korzystam z Bash’a dlatego aliasy uzupełniam w pliku ~/.bashrc. Ten plik wywoływany jest za każdym razem kiedy startujesz Bash’a, a więc np. otwierasz nowe okno terminala lub logujesz się na maszynę przez SSH.
Oto ostatnie dwie linie mojego pliku .bashrc gdzie dodałem dwa polecenia przyśpieszające (delikatnie) pracę z wirtualnymi środowiskami w Pythonie (workon aktywuje środowisko wirtualne, workoff je dezaktywuje):
alias workon='source ./.env/bin/activate' alias workoff='source ./.env/bin/deactivate'Po dodaniu aliasów do .bashrc nie będą działały od razu – Bash nie monitoruje zmian w tym pliku, przetwarza go natomiast przy każdorazowym uruchomieniu nowego shella. Musisz zatem:
- uruchomić ponownie shella (a więc nowe okno terminala/przelogowanie się poprzez SSH, etc.), lub
- użyć komendy source ~/.bashrc która „załaduje” ponownie .bashrc, w tym nowo utworzone aliasy.
Oczywiście samo polecenie alias, np.: alias workon='source ./.env/bin/activate' również zadziała, ale alias który tak stworzysz będzie dostępny tylko do końca bieżącej sesji. Właśnie dlatego potrzebujemy pliku .bashrc – dzięki niemu alias jest zawsze dostępny.
Aliasy niestety nie mogą posiadać parametrów. Więc wykorzystujemy je tam gdzie składnia polecenia jest stała. o ile chcesz użyć parametrów, poczytaj o funkcjach w shellu, np. tutaj: Make a Bash alias that takes a parameter?. Funkcję napisaną w Bashu również wrzucasz do pliku .bashrc – będzie wtedy dostępna w każdym nowo otwartym shellu.
Jak wyszukać polecenia którego kiedyś użyłam/em?
Korzystamy z dwóch podstawowych poleceń oraz | czyli tzw. pipe (rura). Pozwala ona na połączenie strumienia wyjściowego jednego polecenia z wejściem kolejnego. My skorzystamy z cat – aby wyświetlić zawartość całej historii shella oraz grep – aby wyszukać w tej historii wierszy z zadaną frazy.
Zwróć uwagę, iż pracując z Bash’em, historia znajduje się w pliku ~/.bash_history. jeżeli u Ciebie ta kombinacja nie działa – możliwe iż korzystasz z innego shella.
Oczywiście lepiej skorzystać z history, które działa poprawnie w większości dystrybucji i powłok systemowych (piekna fraza, po angielsku shell) a więc:
$ history | grep build docker-compose build docker-compose build docker-compose up --detach --build influxdb docker-compose up --detach --build influxdbW przykładzie powyżej build to wyszukiwana fraza. Grep oczywiście przyjmuje wyrażenia regularne (Regular Expression, regexp czy regex) ale tak jak w przykładzie powyżej – prosta fraza również jest poprawnym parametrem.
Jak wyszukać frazę w całym folderze (rekursywnie)?
Albo inaczej, jak znaleźć wszystkie wystąpienia frazy:
$ grep -rnw . -e 'http:/'To polecenie pokaże wszystkie wystąpienia frazy w plikach ze wskazanego folderu w trybie rekursywnym, a więc z uwzględnieniem zawartości podfolderów. W tym przykładzie szukam frazy http:/ w bieżącym folderze, którego ścieżka w Linuxie to kropka – .. Więcej na temat parametrów których tu użyłem znajdziesz w tej odpowiedzi na Stack Overflow: How do I find all files containing specific text on Linux?
Ten i powyższy przykład zastosowania grep są opisane w tym, dosyć wyczerpującym, artykule o tej komendzie: Grep Command in Linux (Find Text in Files).
Jak skasować cały folder z podfolderami?
$ rm -rf <folder-do-skasowania>Parametr r odpowiada za rekursywność (kasuje podfoldery), dzięki f nie będziemy pytani o potwierdzenia. o ile chcesz skasować coś na prawdę ważnego powyższe polecenie może zwrócić błąd wynikający z nieodpowiednich uprawnień. Wtedy uruchamiasz je jako root korzystając z sudo, tj. sudo rm -rf <folder-do-skasowania>.
Jak zabić proces?
Są dwie drogi – jedna edukacyjna, druga krótka
W tej pierwszej musisz, po pierwsze, znaleźć proces który chcesz usunąć. Polecam do tego polecenie htop, lub, jeżeli masz uboższą bądź starszą dystrybucję – top. Oba polecenia wyświetlają pełnoekranowe (ale działające płynnie na zdalnym terminalu) podsumowania wszystkich uruchomionych procesów. Odnajdzie tam w prosty sposób procesy które konsumują najwięcej zasobów – pamięci RAM lub mocy CPU, lub te które działają najdłużej (mają najdłuższy uptime). o ile chciałbyś raczej polegać na nazwie procesu szukając jego identyfikatora skorzystaj z polecenie ps aux | grep <nazwa-procesu>. Ma ono podobną składnie do opisywanego wyżej poszukiwania uruchamianych poleceń. Korzystamy z łącznika | (pipe) oraz komendy grep. Źródłem dla grep jest tutaj ps aux która to komenda wyświetla wszystkie aktywne procesy.
Niezależnie od tego jak odnajdziesz proces którego chcesz się pozbyć – musisz zwrócić uwagę na jego numer identyfikacyjny – oznaczany jako PID w htop, top oraz ps.
Znając PID możesz wywołać polecenie kill. w uproszczeniu – zabić można na wiele sposobów, o ile chcesz się z tego doktoryzować polecam na początek How to Kill a Process from the Command Line, w mojej praktyce, w zdecydowanej większości przypadków, chcę wysłać sygnał SIGKILL (do którego przypisany jest numer 9). Pozwala on zakończyć „siłowo” uruchomiony proces. Możesz to zrobić poleceniem kill -9 <PID>, więc o ile ja chcę się pozbyć zawiśniętego Sporify’a zrobię to tak:
$ ps aux | grep spotify q 11980 0.4 3.3 5921312 549304 ? Sl Sep11 6:13 /usr/share/spotify/spotify (...) q 31047 0.0 0.0 15644 1104 pts/0 S+ 22:31 0:00 grep --color=auto spotify $ kill -9 11980 $ ps aux | grep spotify q 31053 0.0 0.0 15644 1004 pts/0 S+ 22:31 0:00 grep --color=auto spotifyNa powyższym przykładzie chciałbym zwrócić Twoją uwagę na 2 rzeczy:
- polecenie grep jest również widziane przez ps aux, więc rezultat komendy ps aux | grep <dowolna-fraza> to zawsze przynajmniej jeden proces – właśnie grep.
- często aplikacje desktopowe (te uruchamiane w środowiskach graficznych), tak jak Spotify, posiada wiele aktywnych procesów. W moim wypadku ten o najkrótszej nazwie, który zostawiłem w przykładzie, był procesem nadrzędnym. Pozostałe prawdopodobnie odpowiadały za ikonkę na pasku zadań, logowanie, czy inne, wydzielone zadania. Tutaj musisz albo poprawnie zidentyfikować proces nadrzędny, albo…
Teraz wersja krótka. Tak się składa iż jest ona również odpowiedzią na drugi punkt powyżej (aplikacje z wieloma procesami).
Możesz je wszystkie zakończyć poleceniem killall -9 <część-nazwy-procesu>, np. killall -9 spotify.
Jak przekopiować plik przez SSH?
Popularny scenariusz – masz dostęp do maszyny tylko przez SSH. Żadnego FTP, SFTP, panelu administratora, udziału sieciowego, czy automatyzacji. Jak skopiować na nią lub z niej plik?
Użyj polecenia scp. W najprostszej wersji jego składni jest to komenda scp <źródło> <destynacja>. A więc aby skopiować plik na maszynę zdalną:
scp /home/kuba/plik user@ssh-config:/home/kuba/plik-docelowyŹródłem jest ścieżka lokalna (pełna) pliku który chcesz skopiować, destynacja – URI z uwzględnieniem np. konfiguracji połączenia sieciowego, nazwy użytkownika czy docelowej lokalizacji. o ile chcesz dowiedzieć się jak skonfigurować preset połączenia ssh (a więc host + autentykacja + nazwa użytkownika) przeczytaj mój artykuł Zdalne repozytorium Git na AWS.
Z maszyny zdalnej na lokalną działamy odwrotnie, ale wciąż uruchamiamy scp z maszyny lokalnej (tj. kopiujemy na zdalną, poprzez wysłanie pliku z maszyny lokalnej, kopiujemy do siebie, poprzez żądanie pliku od maszyny zdalnej). Bardziej symetryczny schemat (tj. kopiujemy na zdalną poprzez wysłanie pliku z maszyny lokalnej, kopiujemy do siebie poprzez wysłanie pliku z maszyny zdalnej) jest mniej efektywny i wymaga dodatkowego połączenia z maszyną zdalną oraz konfigurację połączenia z maszyny zdalnej na lokalną. Do brzegu, z maszyny zdalnej na lokalną kopiujemy uruchamiając to polecenie z maszyny lokalnej:
scp user@ssh-config:/home/kuba/plik /home/kuba/plik-docelowyGdzie znajduje się program który uruchamia dana komenda?
Jest to pytanie które warto sobie zadać kiedy coś się zepsuje – upewnij się iż uruchamiasz adekwatny program, we adekwatnej wersji. Możesz po prostu nie ogarniać swojej zmiennej środowiskowej PATH, a może nie jesteś pewna/ien do której z kilku wersji danego programu odnosi się komenda. Ja osobiście często zastanawiam się do której wersji i instancji Pythona w danym środowisku odnosi się komenda python.
Rozwiązanie? Skorzystaj z which:
(.env) kuba@local:~/Documents/projekt/a$ which python /home/kuba/Documents/projekt/a/.env/bin/pythonJak uruchamiać zadanie w określonych odstępach czasu/w określonym harmonogramie?
W skrócie – należy użyć cron’a. Jest to mechanizm wykorzystywany *nixach pozwalający na uruchamianie zadań w określonych interwałach lub w określonym czasie. BTW, nazwa pochodzi od Chronosa, greko-romańskiej personifikacji czasu.
Swoim cron’em zarządzasz przez plik crontab, uruchamiając polecenie crontab -e. Parametr -e otworzy bieżący crontab w domyślnym edytorze tekstowym. Namiar na edytor powinien być dostępny w zmiennej środowiskowej VISUAL lub EDITOR, w przeciwnym razie crontab użyje ścieżki /usr/bin/editor aby odszukać domyślny edytor plików.
Do crontab dodajesz wpisy (wiersze) o określonej strukturze którą w bardzo ładny sposób definiuje artykuł cron w angielskiej Wikipedii:
┌───────────── minute (0 - 59) │ ┌───────────── hour (0 - 23) │ │ ┌───────────── day of the month (1 - 31) │ │ │ ┌───────────── month (1 - 12) │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; │ │ │ │ │ 7 is also Sunday on some systems) │ │ │ │ │ │ │ │ │ │ * * * * * <command to execute>Teraz kilka przykładów tej notacji, za stroną crontab.guru którą bardzo polecam.
Raz na godzinę (a więc reguła brzmi – o każdej zerowej minucie):
0 * * * *Raz dziennie (a więc o 00:00):
0 0 * * *W każdy poniedziałek (a konkretnie o 00:00 w poniedziałek):
0 0 * * MONWięcej przykładów na wspomnianym crontab.guru, a teraz jak wygląda gotowy wiersz crontab uruchamiające np. backup bazy mongo każdego dnia o 04:00 rano:
0 4 * * * /bin/sh /path/to/backup-mongo.shFin
Mam nadzieję iż z czasem uda mi się uzupełnić ten artykuł o kolejne przydatne polecenia w Linuxie, time will tell
P.S.
Zdjęcie tytułowe zrobiłem z ostatniego piętra hotelu „służbowego” Holiday Inn Quingdao Parkview w dzielnicy Chengyang, w mieście Quingdao w Chinach. Gdzieś w okolicach 2015 roku.