Poniżej znajdują się kompletne rozwiązania 10 zadań laboratoryjnych z zakresu programowania w powłoce Bash. Każde rozwiązanie zawiera działający kod skryptu wraz z opisem działania oraz wskazówkami uruchomienia. Wszystkie skrypty zostały zweryfikowane pod kątem poprawności składni.
chmod +x i wywołaniu ścieżką względną ./01_bash_z01.shoceny=() przeznaczoną do przechowywania wprowadzanych przez użytkownika wartościwhile true zapewnia ciągły dialog z użytkownikiem do momentu wpisania słowa kluczowego kończącegoread bez argumentów pobiera całą linię danych od użytkownika do zmiennej wartosc[[ "$wartosc" == "koniec" ]] przy użyciu podwójnych nawiasów [[...]] umożliwiających rozszerzoną składnię porównań=~ ^[0-9]+$ sprawdzające czy ciąg zawiera wyłącznie cyfrywartosc=$((10#$wartosc)) z bazą 10 (10#) zapewniającą poprawne traktowanie zer wiodących[[ ... && ... ]]echo z kolorem czerwonym i program kontynuuje działanie pętlioceny+=("$wartosc") rozszerzającą tablicę przy każdym wpisiefor ocena in "${oceny[@]}" iterującą po wszystkich elementachsrednia=$(( suma / ${#oceny[@]} ))printf "%.2f" formatujące wynik zmiennoprzecinkowy[[ $(echo "$srednia >= 3.0" | bc -l) -eq 1 ]] wykorzystuje program bc do arytmetyki zmiennoprzecinkowejexit 0 sygnalizuje poprawne zakończenie skryptu, a exit 1 wskazuje błąd walidacji danychdeclare -A serwery przechowującą nazwy serwerów jako klucze i ich adresy IP jako wartościserwery[web01]="192.168.1.10"plik_raportu="/tmp/raport_serwery.txt" wskazuje ścieżkę gdzie zapisywane są wyniki monitorowaniarm -f "$plik_raportu" usuwa poprzedni raport przed rozpoczęciem nowego pomiaru, flaga -f pomija pytania potwierdzającefor serwer in "${!serwery[@]}" iteruje po kluczach tablicy asocjacyjnej używając ${!serwery[@]} zwracającego wszystkie kluczeping -c 1 -W 2 "${serwery[$serwer]}" wysyła jedno żądanie ICMP z limitem czasu 2 sekund na odpowiedź$? przechowuje kod wyjścia ostatniego polecenia — wartość 0 oznacza sukces, inne wartości wskazują na błądgrep time i wyrażenia sed wyodrębniającego wartość liczbowądate +"%Y-%m-%d %H:%M:%S" formatującą datę jako rok-miesiąc-dzień godzina:minuta:sekunda >> "$plik_raportu" z operatorem append dodającym linie na końcu pliku bez nadpisywaniaile_online i ile_offline inkrementowane instrukcją ((ile_online++))echo oraz zapisywane do pliku raportu przez przekierowanie >>exit 0 zwracany jest przy poprawnym zakończeniu, umożliwiając integrację z systemami monitoringu takimi jak Nagios czy Zabbixcat /tmp/raport_serwery.txt w celu archiwizacji lub dalszej analizy danychchmod +x 01_bash_z02.sh ./01_bash_z02.sh
cat /tmp/raport_serwery.txt
$1, z domyślną wartością przypisaną przez konstrukcję ${1:-"/tmp/app.log"}[[ -f "$plik_logow" ]] zwracające prawdę gdy plik jest zwykłym plikiemtouch "$plik_logow" i wypełnia przykładowymi danymi za pomocą mechanizmu heredoc cat > "$plik_logow" << EOFgrep "ERROR" filtrujące plik i przekazujące wyniki do dalszego przetwarzania przez potokcut -d' ' -f5- wycinające pole z typem błędu oraz sort | uniq -c sortujące i zliczające duplikatyhead -1 pobiera pierwszą linię z przefiltrowanych błędów wyznaczającą datę pierwszego błędu w plikutail -1 pobiera ostatnią linię z błędami określającą datę ostatniego wystąpienia błędu w logusort -rn według liczby wystąpień i wybranie pierwszego wyniku head -1| łączących wyjście jednego polecenia z wejściem następnego w łańcuchu przetwarzaniablad_typ i blad_liczba do przechowywania wyników analizy w trakcie działania programudate z parametrem +%Y-%m-%d %H:%M:%S formatuje znaczniki czasu w spójny sposób dla czytelności raportu końcowegoif [[ ! -f "$plik_logow" ]]; then sprawdzającą warunek negatywny przed przystąpieniem do analizyexit 0 przy poprawnym zakończeniu analizy lub exit 1 w przypadku błędów krytycznychchmod +x 01_bash_z03.sh ./01_bash_z03.sh
./01_bash_z03.sh /var/log/myapp.log
$1), źródło ($2) i katalog docelowy ($3) określające miejsce zapisu kopii zapasowejcase "$tryb" in pozwalającą na wybór trybu działania między trybem backup a trybem restore[[ $# -lt 3 ]] gwarantujące dostarczenie wszystkich wymaganych parametrów[[ -e "$zrodlo" ]] zwracające prawdę dla plików i katalogów istniejących w systemie plikówdate +"%Y-%m-%d_%H-%M-%S" wstawiające znacznik czasu do nazwy plikunazwa_YYYY-MM-DD_HH-MM-SS.tar.gz zapewnia unikalność plików archiwum i możliwość sortowania chronologicznegomkdir -p "$katalog_docelowy" z flagą -p tworzącą strukturę katalogów nadrzędnychtar -czf tworzy skompresowane archiwum gzip z plików źródłowych, gdzie flaga -c oznacza tworzenie, -z kompresję gzip, -f określa plik wynikowyecho "Tworzę backup: $archiwum" informujący użytkownika o wykonywanej operacjitar -xzf "$archiwum" -C "$katalog_docelowy" z flagą -x oznaczającą rozpakowanie archiwumexit 0 przy sukcesie i exit 1 przy błędzie umożliwiają sprawdzenie statusu operacji w powłoce i skryptach nadrzędnych2>&1 przekierowuje standardowy strumień błędów do standardowego wyjścia dla ujednolicenia komunikatówlatest.tar.gz wskazujący na najnowsze archiwum dla wygodnego dostępu./01_bash_z04.sh backup /home/użytkownik/dane ./01_bash_z04.sh backup "/sciezka/do/pliku" /tmp/backup
./01_bash_z04.sh restore /tmp/backup/dane_2024-01-15_14-30-00.tar.gz /home/użytkownik
$1) określający żądaną długość hasła, domyślnie ustawiony na 16 znaków przez konstrukcję ${1:-16}exit 1znaki_male="a-z", znaki_duze="A-Z", cyfry="0-9" i znaki_specjalne="!@#$%^&*"tr -dc "$zbior" filtruje dane wejściowe zachowując tylko znaki z podanego zbioru, gdzie flaga -d usuwa znaki, -c oznacza komplement/dev/urandom będącego źródłem losowych bajtów w systemie Linux/dev/urandom | tr -dc "$zbior" | head -c "$dlugosc" pobiera losowe znaki z określonego zbioru w żądanej ilościwhile true powtarza proces generowania do momentu spełnienia wszystkich wymagań bezpieczeństwa hasła[[ "$haslo" =~ [A-Z] ]][a-z], cyfry przez [0-9] oraz znaki specjalne przez wzorzec [!@#$%^&*]declare -A sprawdzenie przechowuje informację o spełnieniu każdego warunku bezpieczeństwa hasłaecho "Wygenerowane hasło: $haslo" na standardowym wyjściu/dev/urandom zamiast /dev/random zapewnia nieblokujące generowanie losowych danych[[ "$1" =~ ^[0-9]+$ ]]exit 0 zwracany jest po poprawnym wygenerowaniu hasła spełniającego wszystkie kryteria bezpieczeństwa./01_bash_z05.sh # długość domyślna 16 ./01_bash_z05.sh 12 # długość 12 ./01_bash_z05.sh 24 # długość 24
$1), nazwę lub PID procesu ($2) i opcjonalny typ sygnału ($3)case "$akcja" in rozdzielającą logicznie poszczególne operacje do wykonaniaps aux wyświetla wszystkie procesy użytkownika z pełnymi informacjami o PID, użytkowniku, użyciu CPU i pamięcigrep "$USER" w potoku przetwarzającym wynik polecenia pspgrep -a "$nazwa" zwracające PID i nazwę procesu spełniającego kryteria[[ $pid -le 9 ]] blokujące operacje na procesach init i ich bezpośrednich potomkachkill -TERM $pid wysyła sygnał zakończenia (SIGTERM) do wskazanego procesu, pozwalając mu na czyste zamknięciekill -KILL $pid wymusza natychmiastowe zakończenie procesu sygnałem SIGKILL gdy opcja zostanie podana jako trzeci argument$UID przechowująca identyfikator użytkownika pozwala sprawdzić uprawnienia do wysyłania sygnałów do procesów innych użytkownikówawk wyodrębniającego konkretne kolumnyif kill -0 $pid 2>/dev/null sprawdza czy proces istnieje bez wysyłania mu sygnałuecho informując użytkownika o wykonanej akcji i jej wynikuexit 0 przy sukcesie i exit 1 przy błędzie umożliwiają automatyzację w powłoce i skryptach nadrzędnychsort -n zapewnia czytelność raportów przy wielu procesach./01_bash_z06.sh list ./01_bash_z06.sh find bash ./01_bash_z06.sh kill 1234 ./01_bash_z06.sh kill 1234 KILL
$1), wartość ($2), jednostka źródłowa ($3) i jednostka docelowa ($4)case "$typ" in pozwalającą na wybór odpowiedniego algorytmu przeliczania[[ $# -lt 4 ]] gwarantując dostarczenie wszystkich wymaganych parametrów=~ ^[0-9]*\.?[0-9]+$ obsługujące liczby całkowite i zmiennoprzecinkowe1m = 100cm, 1m = 3.28084ft, 1m = 39.3701cal(c * 9/5) + 32, F do C: (f - 32) * 5/9C = K - 273.15 używając skali bezwzględnej temperatur1kg = 1000g, 1kg = 2.20462lb, 1kg = 35.274ozprintf "%.2f" zapewniające wyświetlenie dwóch miejsc po przecinku"{wartość} {jednostka_źródłowa} = {wynik} {jednostka_docelowa}"exit 0 przy poprawnej konwersji lub exit 1 w przypadku błędnych parametrów wejściowychSCALE=2 definiującą precyzję obliczeń zmiennoprzecinkowych./01_bash_z07.sh dlugosc 100 m ft # 100m -> stopy ./01_bash_z07.sh temperatura 0 c f # 0°C -> °F ./01_bash_z07.sh waga 1 kg lb # 1kg -> funty
01_bash_z08a.sh) zawierającą definicje funkcji logujących oraz skrypt demonstracyjny (01_bash_z08.sh)source 01_bash_z08a.sh lub . 01_bash_z08a.sh wczytujące funkcje do bieżącej powłokifunction log_info() z przekazaniem argumentu jako $@ reprezentującego wszystkie argumenty pozycyjnedate +"%Y-%m-%d %H:%M:%S" generuje znacznik czasu w formacie rok-miesiąc-dzień godzina:minuta:sekunda[${znacznik}] [INFO] ${komunikat} zapewnia spójny i czytelny zapis z rozróżnieniem poziomów ważności>> "$plik_logu" z operatorem append zapobiegającym nadpisywaniu istniejących wpisówcat "$plik_logu" z opcjonalnym filtrowaniem przez argument: > "$plik_logu" tworzącym pusty plik o tej samej nazwiegrep -cif [[ ! -d "$katalog_logow" ]]; then mkdir -p "$katalog_logow"; fi tworzy katalog logów jeśli nie istnieje-w w poleceniu testowym$? po operacji zapisu informuje o ewentualnych problemachplik_logu pozwala na zmianę lokalizacji pliku logów bez modyfikacji kodu funkcjichmod +x 01_bash_z08.sh ./01_bash_z08.sh
$1), tryb transformacji ($2), prefix lub wzorzec ($3) i opcjonalnie opcję --previewcase "$tryb" in rozdzielającą poszczególne operacje zmiany nazwfind "$katalog" -maxdepth 1 -type f wyszukuje pliki w katalogu bez rekursji, flaga -type f oznacza tylko zwykłe plikiwhile IFS= read -r plik odczytuje nazwy plików bez rozdzielania na słowa (IFS) i interpretacji znaków specjalnychmv "$plik" "$(dirname "$plik")/$(basename "$plik" | tr '[:upper:]' '[:lower:]')"tr '[:lower:]' '[:upper:]' konwertujące litery na wielkiemv "$plik" "$(dirname "$plik")/${prefix}$(basename "$plik")"basename "$plik" | sed "s/$stary/$nowy/g" używające wyrażeń regularnych do zamiany wzorców--preview powoduje wyświetlenie planowanych zmian bez ich faktycznego wykonania przez pominięcie polecenia mv[[ -f "$nowa_nazwa" ]] zapobiegające nadpisaniuif [[ ! "$plik" =~ ^.*/$ ]] pomija katalogi w przetwarzaniu weryfikując czy element jest plikiem$licznik przechowuje liczbę zmienionych plików i jest inkrementowana po każdej udanej operacji mv$? po operacji mv informuje o problemach z uprawnieniami lub brakiem miejscaecho "Zmieniono $licznik plików" informuje użytkownika o wyniku operacjibasename i dirname pozwala na prawidłowe obsłużenie ścieżek zawierających spacje i znaki specjalneexit 0 przy sukcesie lub exit 1 w przypadku błędów krytycznych takich jak nieistniejący katalog./01_bash_z09.sh /tmp/pliki lowercase --preview ./01_bash_z09.sh /tmp/pliki prefix img_ ./01_bash_z09.sh /tmp/pliki replace " " "_"
[[ $EUID -eq 0 ]] określającą czy jest wykonywany z uprawnieniami rootpakiety=(git curl wget mc htop) przechowująca nazwy programów do zainstalowaniaapt-get update aktualizuje listę dostępnych pakietów w systemie przed rozpoczęciem instalacji nowego oprogramowaniafor pakiet in "${pakiety[@]}" iteruje po wszystkich elementach tablicy pakietów do przetworzenia i instalacjidpkg -l "$pakiet" 2>/dev/null | grep -q "^ii"apt-get install -y "$pakiet" z flagą -y automatycznie potwierdzającą instalacjędeclare -A aliasy z kluczami jako nazwami aliasów i wartościami jako poleceniami~/.bashrc realizowane jest przez konstrukcję echo "alias ll='ls -la'" >> ~/.bashrcgrep -q "alias ll=" ~/.bashrc zapobiegające duplikatom wpisów~/.bashrc ładowane jest poleceniem source ~/.bashrc aby nowe aliasy były dostępne natychmiastecho informując użytkownika o wykonywanych operacjach2>&1 | tee -a "$log" zapisuje komunikaty błędów do pliku logu i wyświetla je jednocześniemkdir -p /var/log/skrypty przed rozpoczęciem rejestracji zdarzeńexit 0 przy całkowitym sukcesie lub exit 1 gdy instalacja dowolnego pakietu zakończy się niepowodzeniemchmod +x 01_bash_z10.sh sudo ./01_bash_z10.sh # jako root - pełna instalacja ./01_bash_z10.sh # bez roota - tylko aliasy