Automatyzacja Linux/macOS z Bash: Praktyczny Przewodnik
Mateusz Kędziora

Hej, programiści! Zastanawialiście się kiedyś, jak efektywnie zarządzać swoimi systemami Linux lub macOS? A może chcielibyście zautomatyzować nudne, powtarzalne zadania, żeby mieć więcej czasu na rzeczy, które naprawdę lubicie? Jeśli tak, to trafiliście idealnie. Dziś zajmiemy się bashem - językiem skryptowym dostępnym w systemach Linux oraz MacOS!
Czym właściwie jest Bash?
Bash (Bourne Again Shell) to powłoka poleceń, interpreter, a jednocześnie język programowania. To interfejs między Tobą a jądrem systemu operacyjnego. Umożliwia wydawanie poleceń systemowi, uruchamianie programów, zarządzanie plikami i katalogami. Co najważniejsze, Bash pozwala łączyć te polecenia w skrypty, które automatyzują całe sekwencje zadań.
Dlaczego warto używać Bash’a?
- Automatyzacja: Największa zaleta. Po co ręcznie wykonywać serię poleceń, skoro możesz napisać skrypt, który zrobi to za Ciebie? Codzienne kopie zapasowe? Zmiana nazw setek plików? Monitorowanie zasobów serwera? Bash ogarnie to wszystko.
- Uniwersalność: Bash jest domyślną powłoką w większości dystrybucji Linuksa i dostępny jest również dla macOS. Oznacza to, że Twoje skrypty będą działać na wielu systemach bez większych modyfikacji.
- Integracja: Bash świetnie integruje się z innymi narzędziami i programami w systemie. Możesz wywoływać inne skrypty, programy w C++, Pythonie, a nawet łączyć się z bazami danych.
- Dostępność: Bash jest darmowy i open source. Nie musisz płacić za licencje, ani martwić się o ograniczenia.
- Skuteczność: Bash to szybki i skuteczny sposób wykonywania operacji na plikach i systemach.
Podstawowe komendy Bash, które musisz znać:
Zanim zaczniemy pisać skrypty, przyjrzyjmy się kilku podstawowym komendom, które będą nam potrzebne. Traktuj to jako słowniczek początkującego Basha.
ls
(list): Wyświetla listę plików i katalogów w bieżącym katalogu.ls -l
: Wyświetla listę w formacie szczegółowym (uprawnienia, data modyfikacji, rozmiar itp.).ls -a
: Wyświetla wszystkie pliki, w tym ukryte (zaczynające się od kropki).ls -t
: Sortuje pliki według daty modyfikacji (najnowsze na górze).
Przykład:
# Wyświetl zawartość bieżącego katalogu w szczegółowym formacie ls -l
cd
(change directory): Zmienia bieżący katalog.cd ..
: Przechodzi do katalogu nadrzędnego.cd ~
: Przechodzi do katalogu domowego.cd /
: Przechodzi do katalogu głównego.
Przykład:
# Przejdź do katalogu o nazwie "dokumenty" cd dokumenty
mkdir
(make directory): Tworzy nowy katalog.mkdir -p
: Tworzy całą ścieżkę katalogów, jeśli nie istnieją.
Przykład:
# Utwórz katalog o nazwie "nowy_katalog" mkdir nowy_katalog
rm
(remove): Usuwa pliki i katalogi. Używaj tej komendy ostrożnie!rm plik.txt
: Usuwa plik o nazwieplik.txt
.rm -r katalog
: Usuwa katalog i jego zawartość (rekurencyjnie).rm -f plik.txt
: Usuwa plik bez pytania o potwierdzenie.rm -rf katalog
: Usuwa katalog i jego zawartość bez pytania o potwierdzenie. Bardzo niebezpieczne!
Przykład:
# Usuń plik o nazwie "niepotrzebny_plik.txt" rm niepotrzebny_plik.txt # Usuń katalog o nazwie "stary_katalog" wraz z jego zawartością rm -r stary_katalog
cp
(copy): Kopiuje pliki i katalogi.cp plik.txt kopia.txt
: Kopiujeplik.txt
dokopia.txt
.cp -r katalog nowy_katalog
: Kopiuje katalogkatalog
donowy_katalog
(rekurencyjnie).
Przykład:
# Skopiuj plik "ważny_plik.txt" do "kopia_wazny_plik.txt" cp ważny_plik.txt kopia_wazny_plik.txt # Skopiuj katalog "dane" do katalogu "backup_dane" cp -r dane backup_dane
mv
(move): Przenosi lub zmienia nazwę plików i katalogów.mv plik.txt nowy_plik.txt
: Zmienia nazwęplik.txt
nanowy_plik.txt
.mv plik.txt katalog
: Przenosiplik.txt
dokatalog
.
Przykład:
# Zmień nazwę pliku "staranazwa.txt" na "nowanazwa.txt" mv staranazwa.txt nowanazwa.txt # Przenieś plik "plik.txt" do katalogu "dokumenty" mv plik.txt dokumenty
cat
(concatenate): Wyświetla zawartość pliku.Przykład:
# Wyświetl zawartość pliku "raport.txt" cat raport.txt
echo
: Wyświetla tekst.Przykład:
# Wyświetl tekst "Witaj świecie!" echo "Witaj świecie!"
grep
: Wyszukuje wzorce w plikach.grep "wzorzec" plik.txt
: Wyszukuje wplik.txt
wiersze zawierające “wzorzec”.
Przykład:
# Wyszukaj w pliku "log.txt" wiersze zawierające słowo "error" grep "error" log.txt
chmod
(change mode): Zmienia uprawnienia dostępu do plików i katalogów. Używane do definiowania kto może czytać, pisać i wykonywać plik.chmod +x skrypt.sh
: Dodaje uprawnienia do wykonywania skryptu.chmod 755 skrypt.sh
: Ustawia uprawnienia na rwxr-xr-x (właściciel może czytać, pisać i wykonywać, grupa i inni tylko czytać i wykonywać).
Przykład:
# Ustaw uprawnienia do wykonywania skryptu "moj_skrypt.sh" chmod +x moj_skrypt.sh # Ustaw uprawnienia na 755 dla pliku "plik.txt" chmod 755 plik.txt
chown
(change owner): Zmienia właściciela i grupę pliku.chown user:group plik.txt
: Zmienia właściciela nauser
i grupę nagroup
dlaplik.txt
.
Przykład:
# Zmień właściciela pliku "plik.txt" na użytkownika "jan" i grupę "grupa_jan" chown jan:grupa_jan plik.txt
find
: Wyszukuje pliki i katalogi na podstawie różnych kryteriów.find . -name "*.txt"
: Wyszukuje wszystkie pliki z rozszerzeniem.txt
w bieżącym katalogu i jego podkatalogach.find / -size +10M
: Wyszukuje wszystkie pliki większe niż 10 MB w całym systemie plików.
Przykład:
# Wyszukaj wszystkie pliki z rozszerzeniem ".log" w katalogu "/var/log" find /var/log -name "*.log" # Wyszukaj wszystkie pliki większe niż 100MB w katalogu domowym find ~ -size +100M
ps
(process status): Wyświetla informacje o uruchomionych procesach.ps aux
: Wyświetla wszystkie procesy uruchomione przez wszystkich użytkowników.ps -ef
: Podobne dops aux
, ale wyświetla więcej informacji.
Przykład:
# Wyświetl wszystkie uruchomione procesy ps aux
top
: Wyświetla dynamiczny podgląd procesów, które zużywają najwięcej zasobów systemowych (CPU, pamięć).Przykład:
# Uruchom program "top" top
kill
: Wysyła sygnał do procesu, zazwyczaj sygnał zakończenia (SIGTERM).kill PID
: Zabija proces o podanym PID (Process ID).kill -9 PID
: Wysyła sygnał SIGKILL (natychmiastowe zabicie procesu). Używaj ostrożnie!
Przykład:
# Zabij proces o ID 1234 kill 1234 # Zabij proces o ID 5678, używając sygnału SIGKILL kill -9 5678
df
(disk free): Wyświetla informacje o zajętości dysków.df -h
: Wyświetla informacje w formacie czytelnym dla człowieka (np. GB, MB).
Przykład:
# Wyświetl informacje o zajętości dysków w czytelnym formacie df -h
du
(disk usage): Wyświetla informacje o zajętości dysków przez pliki i katalogi.du -sh
: Wyświetla sumaryczny rozmiar bieżącego katalogu w czytelnym formacie.du -h --max-depth=1
: Wyświetla rozmiary katalogów w bieżącym katalogu (do głębokości 1).
Przykład:
# Wyświetl rozmiar bieżącego katalogu w czytelnym formacie du -sh # Wyświetl rozmiary katalogów w bieżącym katalogu du -h --max-depth=1
To tylko wierzchołek góry lodowej, ale te komendy są fundamentem, na którym będziemy budować nasze skrypty.
Pierwszy skrypt Bash: Hello World!
Czas na praktykę. Stwórzmy nasz pierwszy skrypt. Otwórz edytor tekstu (np. nano
, vim
, gedit
) i wpisz następujący kod:
#!/bin/bash
# To jest mój pierwszy skrypt Bash
echo "Witaj świecie!"
Zapisz plik jako hello.sh
. Teraz musimy nadać mu uprawnienia do wykonywania:
chmod +x hello.sh
A następnie uruchom skrypt:
./hello.sh
Powinieneś zobaczyć w terminalu:
Witaj świecie!
Co tu się stało?
#!/bin/bash
: To tak zwany “shebang”. Mówi systemowi, który interpreter ma użyć do wykonania skryptu (w tym przypadku Bash). Musi być to pierwsza linia pliku.# To jest mój pierwszy skrypt Bash
: Komentarz. Bash ignoruje wszystko po znaku#
aż do końca linii. Komentarze są bardzo ważne, żeby Twój kod był czytelny i zrozumiały.echo "Witaj świecie!"
: Wyświetla tekst “Witaj świecie!” na standardowe wyjście (czyli w terminalu).
Zmienne w Bash’u
Zmienne to podstawowy element każdego języka programowania. W Bash’u używamy ich do przechowywania danych, które możemy później wykorzystać w skrypcie.
#!/bin/bash
# Definiowanie zmiennej
imie="Jan"
nazwisko="Kowalski"
# Używanie zmiennej
echo "Witaj, $imie $nazwisko!"
# Zmienne środowiskowe
echo "Twój katalog domowy: $HOME"
echo "Twój użytkownik: $USER"
Wyjaśnienie:
imie="Jan"
: Przypisanie wartości “Jan” do zmiennej o nazwieimie
. Pamiętaj: przed i po znaku=
nie może być spacji!echo "Witaj, $imie $nazwisko!"
: Użycie zmiennych.$
przed nazwą zmiennej powoduje, że Bash podstawi jej wartość. Możemy używać zmiennych wewnątrz ciągów znaków. Jeśli chcesz użyć zmiennej z bardziej złożoną nazwą, np.moja_zmienna
, możesz użyćecho "Wartość: ${moja_zmienna}"
, aby uniknąć niejednoznaczności.$HOME
i$USER
: To zmienne środowiskowe, które są automatycznie ustawiane przez system.$HOME
zawiera ścieżkę do Twojego katalogu domowego, a$USER
Twoją nazwę użytkownika.
Instrukcje warunkowe (if, then, else, fi)
Instrukcje warunkowe pozwalają wykonywać różne fragmenty kodu w zależności od tego, czy dany warunek jest spełniony, czy nie.
#!/bin/bash
plik="plik.txt"
# Sprawdź, czy plik istnieje
if [ -f "$plik" ]; then
echo "Plik $plik istnieje."
else
echo "Plik $plik nie istnieje."
fi
# Porównywanie liczb
liczba1=10
liczba2=20
if [ "$liczba1" -gt "$liczba2" ]; then
echo "$liczba1 jest większe od $liczba2."
elif [ "$liczba1" -lt "$liczba2" ]; then
echo "$liczba1 jest mniejsze od $liczba2."
else
echo "$liczba1 jest równe $liczba2."
fi
Wyjaśnienie:
if [ -f "$plik" ]; then
: Sprawdza, czy plik o nazwie przechowywanej w zmiennejplik
istnieje.[ ]
to polecenie test, a-f
to operator, który sprawdza, czy dany plik jest zwykłym plikiem."$plik"
jest otoczone cudzysłowami, żeby uniknąć problemów, jeśli nazwa pliku zawiera spacje.then
oznacza, że jeśli warunek jest spełniony, to wykonaj kod pothen
.else
: Jeśli warunek wif
nie jest spełniony, wykonaj kod poelse
.fi
: Zamyka instrukcjęif
.elif
: Skrót od “else if”. Pozwala na dodanie kolejnych warunków.-gt
,-lt
,-eq
,-ne
,-ge
,-le
: Operatory porównania liczb.-gt
(greater than),-lt
(less than),-eq
(equal),-ne
(not equal),-ge
(greater or equal),-le
(less or equal).- WAŻNE: Wewnątrz
[ ]
spacje są bardzo ważne.[ "$liczba1" -gt "$liczba2" ]
jest poprawne, ale["$liczba1"-gt"$liczba2"]
już nie.
Pętle (for, while, until)
Pętle pozwalają powtarzać fragment kodu określoną liczbę razy lub dopóki dany warunek jest spełniony.
Pętla
for
:#!/bin/bash # Iteracja po liście plików for plik in *.txt; do echo "Przetwarzam plik: $plik" done # Iteracja po zakresie liczb for i in {1..5}; do echo "Liczba: $i" done # Iteracja po elementach tablicy owoce=("jabłko" "gruszka" "banan") for owoc in "${owoce[@]}"; do echo "Owoc: $owoc" done
Wyjaśnienie:
for plik in *.txt; do
: Iteruje po wszystkich plikach z rozszerzeniem.txt
w bieżącym katalogu.*.txt
to wzorzec globbing, który pasuje do wszystkich plików z tym rozszerzeniem.done
: Zamyka pętlęfor
.for i in {1..5}; do
: Iteruje po zakresie liczb od 1 do 5.owoce=("jabłko" "gruszka" "banan")
: Definicja tablicy."${owoce[@]}"
: Rozwija tablicęowoce
do listy elementów. Cudzysłowy są ważne, żeby uniknąć problemów, jeśli elementy tablicy zawierają spacje.
Pętla
while
:#!/bin/bash licznik=1 while [ "$licznik" -le 5 ]; do echo "Licznik: $licznik" licznik=$((licznik + 1)) done
Wyjaśnienie:
while [ "$licznik" -le 5 ]; do
: Wykonuje kod w pętli dopóki wartość zmiennejlicznik
jest mniejsza lub równa 5.licznik=$((licznik + 1))
: Zwiększa wartość zmiennejlicznik
o 1.$((...))
to notacja arytmetyczna w Bash’u.
Pętla
until
:#!/bin/bash licznik=1 until [ "$licznik" -gt 5 ]; do echo "Licznik: $licznik" licznik=$((licznik + 1)) done
Wyjaśnienie:
until [ "$licznik" -gt 5 ]; do
: Wykonuje kod w pętli dopóki wartość zmiennejlicznik
nie jest większa od 5. Inaczej mówiąc, pętla wykonuje się dopóki warunek jest fałszywy.
Funkcje
Funkcje pozwalają na grupowanie fragmentów kodu, które wykonują konkretne zadanie. Możemy je wywoływać wielokrotnie z różnych miejsc w skrypcie.
#!/bin/bash
# Definicja funkcji
funkcja_przywitanie() {
echo "Witaj, $1!"
}
# Wywołanie funkcji
funkcja_przywitanie "Jan"
funkcja_przywitanie "Anna"
# Funkcja z wartością zwrotną
funkcja_suma() {
local suma=$(( $1 + $2 ))
echo $suma
}
wynik=$(funkcja_suma 10 20)
echo "Suma: $wynik"
Wyjaśnienie:
funkcja_przywitanie() { ... }
: Definicja funkcji o nazwiefunkcja_przywitanie
.$1
: Pierwszy argument przekazany do funkcji.$2
to drugi argument,$3
to trzeci, i tak dalej.funkcja_przywitanie "Jan"
: Wywołanie funkcji z argumentem “Jan”.local suma=$(( $1 + $2 ))
: Deklaracja zmiennej lokalnejsuma
.local
oznacza, że zmienna jest widoczna tylko wewnątrz funkcji.echo $suma
: Funkcja zwraca wartość poprzez wypisanie jej na standardowe wyjście.wynik=$(funkcja_suma 10 20)
: Wywołanie funkcji i przypisanie jej wyniku do zmiennejwynik
.$(...)
to command substitution, która pozwala na wykonanie polecenia i podstawienie jego wyniku w danym miejscu.
Przykłady skryptów automatyzujących typowe zadania
Teraz pokażę kilka konkretnych przykładów skryptów, które mogą Ci się przydać w codziennej pracy.
Skrypt do tworzenia kopii zapasowych
#!/bin/bash
# Katalog do skopiowania
source_dir="/home/user/dokumenty"
# Katalog docelowy dla kopii zapasowej
backup_dir="/home/user/backup"
# Nazwa pliku kopii zapasowej
backup_file="backup_$(date +%Y-%m-%d_%H-%M-%S).tar.gz"
# Sprawdź, czy katalog docelowy istnieje
if [ ! -d "$backup_dir" ]; then
echo "Katalog docelowy $backup_dir nie istnieje. Tworzę go..."
mkdir -p "$backup_dir"
fi
# Utwórz kopię zapasową
tar -czvf "$backup_dir/$backup_file" "$source_dir"
# Sprawdź, czy kopia zapasowa została utworzona poprawnie
if [ -f "$backup_dir/$backup_file" ]; then
echo "Kopia zapasowa została utworzona pomyślnie: $backup_dir/$backup_file"
else
echo "Błąd podczas tworzenia kopii zapasowej!"
exit 1 # Zakończ skrypt z kodem błędu
fi
exit 0 # Zakończ skrypt z kodem sukcesu
Wyjaśnienie:
- Skrypt tworzy kopię zapasową katalogu
dokumenty
w katalogubackup
. - Nazwa pliku kopii zapasowej zawiera datę i godzinę utworzenia.
- Używamy
tar
do spakowania i skompresowania katalogu. - Skrypt sprawdza, czy katalog docelowy istnieje i tworzy go, jeśli nie istnieje.
- Skrypt sprawdza, czy kopia zapasowa została utworzona poprawnie.
exit 0
oznacza, że skrypt zakończył się pomyślnie.exit 1
oznacza, że wystąpił błąd. Kody wyjścia są używane do sygnalizowania statusu wykonania skryptu innym programom lub skryptom.
Skrypt do wsadowej zmiany nazw plików
#!/bin/bash
# Wzorzec plików do zmiany nazw
wzorzec="plik_*.txt"
# Nowy przedrostek dla nazw plików
nowy_przedrostek="nowy_"
# Iteruj po wszystkich plikach pasujących do wzorca
for plik in $wzorzec; do
# Pobierz starą nazwę pliku
stara_nazwa="$plik"
# Pobierz nową nazwę pliku
nowa_nazwa="${plik/plik_/$nowy_przedrostek}" # Zamień "plik_" na "nowy_"
# Zmień nazwę pliku
mv "$stara_nazwa" "$nowa_nazwa"
echo "Zmieniono nazwę pliku: $stara_nazwa -> $nowa_nazwa"
done
Wyjaśnienie:
- Skrypt zmienia nazwy wszystkich plików pasujących do wzorca
plik_*.txt
w bieżącym katalogu. - Zamienia przedrostek
plik_
nanowy_
. - Używamy
mv
do zmiany nazwy pliku. ${plik/plik_/$nowy_przedrostek}
to parametr expansion, który pozwala na manipulowanie wartością zmiennej. W tym przypadku zamieniamy fragment nazwy pliku.
Skrypt do monitorowania stanu systemu
#!/bin/bash
# Próg wykorzystania CPU (w procentach)
cpu_prog=80
# Próg wykorzystania pamięci (w procentach)
pamiec_prog=90
# Pobierz wykorzystanie CPU
cpu_wykorzystanie=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
# Pobierz wykorzystanie pamięci
pamiec_wykorzystanie=$(free | awk '/Mem:/ {print $3/$2 * 100.0}')
# Sprawdź, czy przekroczono próg wykorzystania CPU
if (( $(echo "$cpu_wykorzystanie > $cpu_prog" | bc -l) )); then
echo "Ostrzeżenie: Wykorzystanie CPU przekroczyło $cpu_prog%: $cpu_wykorzystanie%"
fi
# Sprawdź, czy przekroczono próg wykorzystania pamięci
if (( $(echo "$pamiec_wykorzystanie > $pamiec_prog" | bc -l) )); then
echo "Ostrzeżenie: Wykorzystanie pamięci przekroczyło $pamiec_prog%: $pamiec_wykorzystanie%"
fi
Wyjaśnienie:
- Skrypt monitoruje wykorzystanie CPU i pamięci.
- Używa
top
ifree
do pobrania informacji o stanie systemu. - Porównuje wykorzystanie CPU i pamięci z zdefiniowanymi progami.
- Wyświetla ostrzeżenie, jeśli próg został przekroczony.
bc -l
jest używane do wykonywania operacji na liczbach zmiennoprzecinkowych. Bash domyślnie operuje tylko na liczbach całkowitych.
Wskazówki dla początkujących
- Czytaj dokumentację:
man bash
to Twój najlepszy przyjaciel. Znajdziesz tam szczegółowe informacje o wszystkich komendach i funkcjach Bash’a. - Eksperymentuj: Nie bój się próbować różnych rzeczy. Najlepszym sposobem na naukę jest praktyka.
- Używaj komentarzy: Komentuj swój kod, żeby był czytelny i zrozumiały. Nawet dla Ciebie w przyszłości!
- Szukaj w internecie: Jeśli masz problem, prawdopodobnie ktoś inny już go rozwiązał. Google i Stack Overflow to Twoi sprzymierzeńcy.
- Debuguj krok po kroku: Używaj opcji
-x
do debugowania skryptu.bash -x skrypt.sh
wyświetli każdy wiersz skryptu przed jego wykonaniem, co pomoże Ci zrozumieć, co się dzieje. - Wykorzystaj narzędzia: Używaj
shellcheck skrypt.sh
do analizy statycznej skryptu i wychwycenia potencjalnych błędów.
Dodatkowe materiały do nauki
- Oficjalna dokumentacja Bash’a: https://www.gnu.org/software/bash/manual/bash.html
- Advanced Bash-Scripting Guide: https://tldp.org/LDP/abs/html/
- Bash scripting tutorial (tutorialspoint): https://www.tutorialspoint.com/unix/shell_scripting.htm
- Learn Shell Scripting (freeCodeCamp): https://www.freecodecamp.org/news/shell-scripting-tutorial-how-to-write-bash-scripts-in-linux/
- Bash Scripting for Beginners (Udemy): (Wiele kursów, sprawdź recenzje przed zakupem).
Podsumowanie
Bash scripting to niezwykle przydatne narzędzie dla każdego, kto pracuje z systemami Linux i macOS. Pozwala na automatyzację zadań, oszczędność czasu i zwiększenie efektywności. Ten artykuł to dopiero początek Twojej przygody z Bash’em. Zachęcam do eksperymentowania, czytania dokumentacji i pogłębiania wiedzy. W kolejnych postach omówimy bardziej zaawansowane techniki, takie jak wyrażenia regularne, praca z plikami konfiguracyjnymi i tworzenie interaktywnych skryptów.
Do zobaczenia wkrótce! I pamiętaj: najlepszy sposób na naukę to praktyka!
Polecane artykuły
Docker vs Kubernetes: Który dla Ciebie w 2025?
Docker i Kubernetes objaśnione! Która technologia lepsza dla początkujących w 2025? Porównanie, przykłady i przyszłość.
Mateusz Kędziora
DevOps: Automatyzacja zadań sysadmina dla programistów
Zautomatyzuj pracę sysadmina w środowisku DevOps! Praktyczne przykłady, skrypty, Ansible, Terraform, Prometheus i Grafana.
Mateusz Kędziora
Testowanie z AI: Jak sztuczna inteligencja zmienia QA?
Zautomatyzuj testy z AI! Zredukuj koszty, przyspiesz proces, zwiększ pokrycie i popraw jakość oprogramowania. Sprawdź, jak to zrobić!
Mateusz Kędziora