Linux: przydatne polecenia

Qingdao, Chiny, 2015?

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). Jeżeli korzystasz z innych dystrybucji możliwe że 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)

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:

  1. uruchomić ponownie shella (a więc nowe okno terminala/przelogowanie się poprzez SSH, etc.), lub
  2. 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.

Uprzedzając Twoje pytanie – aliasy nie mogą posiadać parametrów. Więc wykorzystujemy je tam gdzie składnia polecenia jest stała. Jeżeli 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.

$ cat ~/.bash_history | grep build 
docker-compose build 
docker-compose build 
docker-compose up --detach --build influxdb 
docker-compose up --detach --build influxdb

Zwróć uwagę, że pracując z Bash’em, historia znajduje się w pliku ~/.bash_history. Jeśli u Ciebie ta kombinacja nie działa – możliwe że korzystasz z innego shella. W przykładzie powyżej build to oczywiście 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. Jeżeli 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śli 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). Jeżeli 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 skrócie – zabić można na wiele sposobów, jeżeli 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 jeżeli 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 spotify

Na powyższym przykładzie chciałbym zwrócić Twoją uwagę na 2 rzeczy:

  1. 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.
  2. 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 że 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. Jeżeli 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-docelowy

Gdzie znajduje się program który uruchamia dana komenda?

Jest to pytanie które warto sobie zadać kiedy coś się zepsuje – upewnij się że uruchamiasz właściwy program, we właściwej 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/python

Jak 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 * * MON

Wię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.sh

Fin

Mam nadzieję że 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.

Avatar

Autor: kuba

Pracuję w IT, sprzedając oprogramowanie klasy APS/MES firmom produkcyjnym. Nie jestem software developerem ale odkąd zacząłem w Turbo Pascalu zawsze coś piszę - ostatnio w Pythonie. Lubię technologie, mocną kawę i dobre zdjęcia 🤙

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *