1/16 Zmienne systemowe i użytkownika w skryptach Linux
2/16 1. Wprowadzenie do zmiennych w systemach Unix/Linux

Systemy operacyjne z rodziny Unix i Linux opierają swoje działanie na rozbudowanym systemie zmiennych konfiguracyjnych, które definiują środowisko pracy użytkownika, zachowanie powłoki oraz parametry działających procesów. W przeciwieństwie do systemów Windows, gdzie zmienne środowiskowe mają charakter hierarchiczny z rejestrem jako centralnym repozytorium, w Linuxie dominuje model tekstowy z plikami konfiguracyjnymi i mechanizmami dziedziczenia przez procesy potomne. Ta fundamentalna różnica w architekturze wpływa na sposób zarządzania, wyświetlania i modyfikacji zmiennych.

Zrozumienie mechanizmów zmiennych w Linux jest kluczowe dla administratorów systemów, programistów i wszystkich użytkowników pracujących z linią poleceń. Skrypty powłoki (Bash, sh, zsh) stanowią podstawowe narzędzie automatyzacji w środowiskach serwerowych, a ich efektywne wykorzystanie wymaga biegłej znajomości zarządzania zmiennymi. Linux oferuje również znacznie bardziej rozbudowany model zmiennych niż klasyczne Windows CMD, obejmujący tablice, zmienne asocjacyjne, funkcje ze zmiennymi lokalnymi oraz zaawansowane operacje na ciągach tekstowych.

3/16 2. Architektura zmiennych w Linux

Model zmiennych w systemach Linux opiera się na kilku fundamentalnych koncepcjach, które determinują zachowanie, zasięg i czas życia zmiennych. Zrozumienie tej architektury jest niezbędne dla świadomego zarządzania środowiskiem i pisania efektywnych skryptów.

2.1 Typy zmiennych według zasięgu

W kontekście systemów Linux wyróżniamy następujące kategorie zmiennych, różniące się poziomem dostępności i czasem życia:

  • Zmienne środowiskowe (Environment Variables) – zmienne widoczne dla wszystkich procesów uruchomionych (jako potomków) w systemie, dziedziczone przez procesy potomne. Definiowane na poziomie systemu lub użytkownika i przechowywane w plikach konfiguracyjnych.
  • Zmienne powłoki (Shell Variables) – zmienne dostępne tylko w bieżącej powłoce lub jej podpowłokach, niewidoczne dla innych procesów. Tworzone lokalnie przez użytkownika lub skrypt.
  • Zmienne globalne (Global) – zmienne środowiskowe widoczne dla wszystkich użytkowników i procesów w systemie, definiowane w plikach systemowych (/etc/environment, /etc/profile).
  • Zmienne lokalne (Local) – zmienne definiowane wewnątrz funkcji lub skryptu, niewidoczne poza ich kontekstem.
  • Zmienne readonly – zmienne stałe, których wartość nie może być zmieniona po inicjalizacji.

2.2 Hierarchia i dziedziczenie

Każdy nowo uruchomiony proces w Linux otrzymuje kopię zmiennych środowiskowych od procesu macierzystego. Jest to fundamentalna cecha systemów Unix, zwana fork-exec – proces potomny dziedziczy środowisko rodzica, ale wszystkie modyfikacje dotyczą tylko jego własnej kopii. Oryginalne zmienne procesu macierzystego pozostają niezmienione, chyba że użyto specjalnych mechanizmów komunikacji międzyprocesowej.

# Proces potomny dziedziczy zmienne środowiskowe $ WIADOMOSC="Cześć z rodzica" $ bash -c 'echo $WIADOMOSC' Cześć z rodzica # Zmiany w podpowłoce nie wpływają na rodzica $ bash -c 'WIADOMOSC="Zmieniona"; echo $WIADOMOSC' Zmieniona $ echo $WIADOMOSC Cześć z rodzica # Eksport zmiennej czyni ją widoczną dla potomków $ export WIADOMOSC $ bash -c 'echo $WIADOMOSC' Cześć z rodzica

2.3 Pliki konfiguracyjne i źródła zmiennych

Zmienne środowiskowe w Linux są definiowane w różnych plikach konfiguracyjnych, które są wczytywane w określonej kolejności. Kolejność ta determinuje, która wartość zmiennej ma pierwszeństwo w przypadku wielokrotnej definicji.

  • /etc/environment – plik systemowy zawierający zmienne środowiskowe dla wszystkich użytkowników. Wczytywany przy logowaniu.
  • /etc/profile – skrypt wykonywany dla wszystkich użytkowników podczas logowania (powłoki logowania).
  • /etc/bash.bashrc – plik konfiguracyjny Bash dla wszystkich użytkowników uruchamiających interaktywną powłokę.
  • ~/.bash_profile – plik użytkownika wczytywany przy logowaniu (dla powłok logowania).
  • ~/.bashrc – plik użytkownika wczytywany przy uruchomieniu interaktywnej powłoki nielogowania.
  • ~/.profile – alternatywny plik profilu użytkownika, używany gdy ~/.bash_profile nie istnieje.
4/16 3. Wyświetlanie zmiennych

Linux oferuje kilka poleceń do wyświetlania zmiennych środowiskowych i powłoki. Każde z nich ma nieco inne zastosowanie i zwraca różne typy zmiennych.

3.1 Polecenia env i printenv

Polecenia env i printenv służą do wyświetlania zmiennych środowiskowych. Różnica polega na tym, że env może być użyte również do uruchomienia programu ze zmodyfikowanym środowiskiem, podczas gdy printenv służy wyłącznie do wyświetlania.

# Wyświetl wszystkie zmienne środowiskowe $ env HOME=/home/użytkownik PATH=/usr/local/bin:/usr/bin:/bin USER=użytkownik ... # To samo za pomocą printenv $ printenv HOME=/home/użytkownik PATH=/usr/local/bin:/usr/bin:/bin ... # Wyświetl konkretną zmienną $ printenv HOME /home/użytkownik # Wyszukaj zmienne zawierające określony wzorzec $ env | grep "^PATH" PATH=/usr/local/bin:/usr/bin:/bin

3.2 Polecenie echo i odwołania do zmiennych

Polecenie echo w połączeniu ze specjalną składnią $NAZWA_ZMIENNEJ służy do wyświetlania wartości zmiennych. Znak dolara informuje powłokę, że ma podstawić wartość zmiennej w miejsce jej nazwy.

# Wyświetl zmienną za pomocą echo $ echo $HOME /home/użytkownik $ echo $USER użytkownik $ echo $PWD /home/użytkownik/Dokumenty # Wyświetl wiele zmiennych $ echo "Użytkownik: $USER, Katalog: $HOME" Użytkownik: użytkownik, Katalog: /home/użytkownik # Bezpieczne wyświetlanie (wartość w cudzysłowach) $ echo "$HOME" /home/użytkownik

3.3 Polecenie set

Polecenie set bez parametrów wyświetla wszystkie zmienne powłoki (zarówno te środowiskowe jak i lokalne), funkcje powłoki oraz ustawienia powłoki. Jest to znacznie szerszy zestaw niż oferowany przez env.

# Wyświetl wszystkie zmienne i funkcje powłoki $ set BASH=/bin/bash BASH_ALIASES=() BASH_ARGC=() BASH_CMDS=() ... HOME=/home/użytkownik ... # set z argumentem - pokazuje zmienne zaczynające się od podanego ciągu $ set | grep "^H" HISTFILE=/home/użytkownik/.bash_history HISTFILESIZE=2000 HOME=/home/użytkownik HOSTNAME=serwer01 HOSTTYPE=x86_64 # Lista wszystkich zdefiniowanych zmiennych $ declare -p declare -x HOME="/home/użytkownik" declare -x HOSTNAME="serwer01" declare -- MOJA_ZMIENNA="wartość"
5/16 4. Kompletna lista zmiennych systemowych Linux

Systemy Linux definiują szereg standardowych zmiennych środowiskowych, które są ustawiane przez system init, menedżer logowania i powłokę. Niżej przedstawiono najważniejsze z nich wraz ze szczegółowym opisem ich zastosowania.

4.1 Zmienne dotyczące użytkownika i sesji

  • HOME – ścieżka do katalogu domowego bieżącego użytkownika. Wskazuje lokalizację przechowywania plików użytkownika, plików konfiguracyjnych powłoki (.bashrc, .profile) oraz podfolderów (Dokumenty, Pulpit itp.). Jest to fundamentalna zmienna używana w niemal każdym skrypcie operującym na plikach użytkownika.
  • USER lub USERNAME – nazwa bieżącego zalogowanego użytkownika. Przydatna do personalizacji komunikatów, logowania działań i określania uprawnień.
  • UID – numeryczny identyfikator użytkownika (User ID). W przeciwieństwie do nazwy, UID jest stały dla danego konta i nie zmienia się przy zmianie nazwy użytkownika.
  • GID – numeryczny identyfikator głównej grupy użytkownika (Group ID). Często dostępny jako zmienna środowiskowa, choć rzadziej niż UID.
  • GROUPS – lista identyfikatorów grup, do których należy użytkownik (oddzielonych spacjami). W Bash jest to zwykle tablica.
  • SHELL – pełna ścieżka do domyślnej powłoki użytkownika (np. /bin/bash, /bin/zsh, /bin/sh). Określa powłokę uruchamianą przy logowaniu.
  • LOGNAME – nazwa użytkownika używana do logowania. Może różnić się od USER w niektórych kontekstach.
  • PWD – aktualny katalog roboczy (Print Working Directory). Automatycznie aktualizowany przy każdym poleceniu cd.
  • OLDPWD – poprzedni katalog roboczy. Umożliwia szybkie przechodzenie między dwoma katalogami za pomocą polecenia cd -.

4.2 Zmienne dotyczące systemu operacyjnego

  • HOSTNAME – nazwa hosta systemu w sieci. Identyfikuje maszynę w środowiskach wielomaszynowych i jest używana w komunikatach, logach i konfiguracjach sieciowych.
  • HOSTTYPE – typ architektury sprzętowej (np. x86_64, i686, armv7l). Pozwala skryptom na dostosowanie zachowania do platformy sprzętowej.
  • MACHTYPE – pełna specyfikacja platformy sprzętowej i systemowej (format tupli).
  • OSTYPE – typ systemu operacyjnego (np. linux-gnu, darwin dla macOS).
  • TERM – typ terminala lub emulatora terminala (np. xterm-256color, vt100, screen). Określa zdolności wyświetlania i sekwencje sterujące.
  • DISPLAY – numer wyświetlacza X11 dla aplikacji graficznych. W formacie :0 dla lokalnego wyświetlacza, :10.0 dla zdalnych.
  • TERMINFO – ścieżka do bazy danych opisów terminali.

4.3 Zmienne dotyczące ścieżek i katalogów

  • PATH – lista katalogów (oddzielonych dwukropkami) przeszukiwanych przy uruchamianiu poleceń bez podawania pełnej ścieżki. Jest to najważniejsza zmienna dla funkcjonalności systemu.
  • CDPATH – lista katalogów przeszukiwanych przez polecenie cd. Umożliwia szybkie przechodzenie do często używanych lokalizacji.
  • MANPATH – lista katalogów zawierających strony podręcznika man.
  • INFOPATH – lista katalogów zawierających dokumentację info.
  • LD_LIBRARY_PATH – lista katalogów przeszukiwanych przez linker dynamiczny przy ładowaniu bibliotek współdzielonych.
  • LD_PRELOAD – lista bibliotek ładowanych przed wszystkimi innymi (używane do debugowania i wstrzykiwania kodu).

4.4 Zmienne dotyczące lokalizacji i języka

  • LANG – domyślne ustawienia lokalizacji i języka dla wszystkich kategorii LC_. Określa kodowanie znaków, format daty, liczb i walut.
  • LC_ALL – nadpisuje wszystkie ustawienia lokalizacji. Jeśli ustawiona, ma pierwszeństwo przed LANG i innymi zmiennymi LC_.
  • LC_MESSAGES – język komunikatów programów.
  • LC_TIME – format daty i czasu.
  • LC_NUMERIC – format liczb (separator dziesiętny).
  • LC_COLLATE – kolejność sortowania znaków.
  • TZ – strefa czasowa (np. Europe/Warsaw, America/New_York).

4.5 Zmienne dotyczące sesji powłoki

  • BASH – pełna ścieżka do pliku wykonywalnego powłoki Bash.
  • BASH_VERSION – wersja powłoki Bash w formacie czytelnym dla człowieka.
  • BASH_VERSINFO – szczegółowa wersja Bash w formacie tablicowym.
  • SHELLOPTS – lista włączonych opcji powłoki (oddzielona dwukropkami).
  • IFS – separator pól wejściowych (Internal Field Separator). Domyślnie spacja, tabulator, nowa linia.
  • PS1 – definicja głównego znaku zachęty powłoki. Może zawierać informacje o użytkowniku, hoście, katalogu, gałęzi git.
  • PS2 – znak zachęty dla kontynuacji wiersza (gdy polecenie nie zostało zamknięte).
  • PS4 – znak zachęty dla debugowania (tryb set -x).

4.6 Zmienne historii poleceń

  • HISTCONTROL – kontroluje, co jest zapisywane do historii (ignoredups, ignorespace, ignoreboth).
  • HISTIGNORE – wzorce poleceń pomijanych w historii.
  • HISTFILE – ścieżka do pliku historii poleceń (domyślnie ~/.bash_history).
  • HISTSIZE – maksymalna liczba poleceń zapisywana w historii bieżącej sesji.
  • HISTFILESIZE – maksymalna liczba linii w pliku historii.
  • HISTTIMEFORMAT – format znacznika czasu dla historii (np. "%Y-%m-%d %H:%M:%S").

4.7 Zmienne poczty

  • MAIL – ścieżka do skrzynki pocztowej użytkownika. Powłoka sprawdza ten plik i informuje o nowych wiadomościach.
  • MAILCHECK – interwał (w sekundach) sprawdzania skrzynki pocztowej. Domyślnie 60.
6/16 5. Tworzenie i modyfikacja zmiennych

Tworzenie zmiennych w powłokach uniksowych wymaga zrozumienia fundamentalnej różnicy między zmiennymi powłoki a zmiennymi środowiskowymi. Zmienne powłoki istnieją tylko w bieżącej powłoce i nie są dziedziczone przez procesy potomne. Aby zmienna była widoczna dla innych programów, musi zostać wyeksportowana do środowiska.

5.1 Podstawowe operacje na zmiennych

Proste przypisanie zmiennej tworzy zmienną powłoki, która nie jest eksportowana do środowiska. Aby zmienna stała się zmienną środowiskową, należy użyć polecenia export.

# Tworzenie zmiennej powłoki (lokalna) $ MOJA_ZMIENNA="tekst" $ echo $MOJA_ZMIENNA tekst # Zmienna nie jest widoczna dla podpowłoki $ bash -c 'echo $MOJA_ZMIENNA' (puste) # Eksport zmiennej - teraz widoczna dla potomków $ export MOJA_ZMIENNA $ bash -c 'echo $MOJA_ZMIENNA' tekst # Eksport i przypisanie w jednej linii $ export INNA_ZMIENNA="wartość" $ bash -c 'echo $INNA_ZMIENNA' wartość

5.2 Polecenie export i jego opcje

Polecenie export służy nie tylko do eksportowania zmiennych, ale również do wyświetlania listy eksportowanych zmiennych oraz tworzenia zmiennych tylko do odczytu.

# Wyświetl listę eksportowanych zmiennych $ export -p declare -x HOME="/home/użytkownik" declare -x PATH="/usr/local/bin:/usr/bin:/bin" ... # Usuń atrybut eksportu (zmienna pozostaje w powłoce, ale nie będzie dziedziczona) $ export -n MOJA_ZMIENNA # Eksport ze specjalnym atrybutem (tylko do odczytu) $ declare -r -x STALA_WARTOSC="niemodyfikowalna" $ STALA_WARTOSC="nowa" bash: STALA_WARTOSC: readonly variable

5.3 Polecenie unset

Polecenie unset usuwa zmienną z bieżącej powłoki. Może być użyte zarówno dla zmiennych powłoki, jak i zmiennych środowiskowych (ale tylko w bieżącej powłoce, nie w procesach potomnych).

# Usuń zmienną $ MOJA_ZMIENNA="do usunięcia" $ unset MOJA_ZMIENNA $ echo $MOJA_ZMIENNA (puste) # Nie można usunąć zmiennych tylko do odczytu $ readonly STALA="wartość" $ unset STALA bash: unset: STALA: cannot unset: readonly variable

5.4 Polecenie readonly

Polecenie readonly oznacza zmienną jako "tylko do odczytu", co uniemożliwia jej późniejszą modyfikację lub usunięcie. Jest to przydatne do definiowania stałych konfiguracyjnych w skryptach.

# Zdefiniuj zmienną tylko do odczytu $ readonly WERSJA_APLIKACJI="1.0.0" $ readonly KATALOG_GLOWNY="/opt/aplikacja" $ echo $WERSJA_APLIKACJI 1.0.0 # Próba modyfikacji kończy się błędem $ WERSJA_APLIKACJI="2.0.0" bash: WERSJA_APLIKACJI: readonly variable # Lista zmiennych tylko do odczytu $ readonly -p declare -r WERSJA_APLIKACJI="1.0.0" declare -r KATALOG_GLOWNY="/opt/aplikacja"
7/16 6. Zmienne lokalne w skryptach Bash

W powłoce Bash zmienne są domyślnie "globalne" dla bieżącej powłoki. Jednak wewnątrz funkcji można jawnie definiować zmienne lokalne, które nie będą kolidować ze zmiennymi o tych samych nazwach w innych częściach skryptu. Polecenie local ogranicza zasięg zmiennej do bieżącej funkcji.

6.1 Polecenie local

Polecenie local tworzy zmienną lokalną wewnątrz funkcji. Zmienna ta istnieje tylko w czasie wykonywania funkcji i jest niewidoczna poza nią. Jest to fundamentalny mechanizm izolacji zmiennych w profesjonalnych skryptach Bash.

# Przykład zmiennych lokalnych w funkcji funkcja_testowa() { local zmienna_lokalna="Jestem lokalna" echo "Wewnątrz funkcji: $zmienna_lokalna" echo "Zmienna globalna: $zmienna_globalna" } zmienna_globalna="Jestem globalna" funkcja_testowa Wewnątrz funkcji: Jestem lokalna Zmienna globalna: Jestem globalna $ echo $zmienna_lokalna (puste - zmienna nie istnieje poza funkcją) $ echo $zmienna_globalna Jestem globalna

6.2 Zmienne lokalne a modyfikacja zmiennych globalnych

Wewnątrz funkcji można zarówno odczytywać, jak i modyfikować zmienne globalne. Jednak tworzenie zmiennej lokalnej o tej samej nazwie, co zmienna globalna, tymczasowo "zasłania" tę globalną w zakresie funkcji.

# Modyfikacja zmiennej globalnej wewnątrz funkcji LICZNIK=0 inkrementuj() { LICZNIK=$((LICZNIK + 1)) } inkrementuj echo $LICZNIK 1 # Zmienna lokalna "zasłania" globalną ZMIENNA="globalna" funkcja_z_lokalna() { local ZMIENNA="lokalna" echo "Wewnątrz: $ZMIENNA" } funkcja_z_lokalna Wewnątrz: lokalna $ echo "Na zewnątrz: $ZMIENNA" Na zewnątrz: globalna

6.3 Deklaracje zmiennych - declare i typeset

Polecenia declare i typeset (typeset jest przestarzałym synonimem declare) pozwalają na definiowanie zmiennych z określonymi atrybutami. Są one szczególnie przydatne do tworzenia zmiennych tablicowych, zmiennych tylko do odczytu oraz zmiennych całkowitoliczbowych.

# Deklaracja zmiennej całkowitoliczbowej $ declare -i CALKOWITA=42 $ CALKOWITA="tekst" $ echo $CALKOWITA 0 # Deklaracja zmiennej tablicowej $ declare -a MOJA_TABLICA $ MOJA_TABLICA=(element1 element2 element3) # Deklaracja zmiennej asocjacyjnej (tylko Bash 4+) $ declare -A SLOWNIK $ SLOWNIK[klucz1]="wartość1" $ SLOWNIK[klucz2]="wartość2" # Deklaracja zmiennej środowiskowej $ declare -x MOJE_SRODOWISKO="wartość" # Deklaracja zmiennej tylko do odczytu $ declare -r STALA="wartosc"
8/16 7. Zmienne specjalne powłoki Bash

Bash udostępnia szereg zmiennych specjalnych, które mają predefiniowane znaczenie i są automatycznie ustawiane przez powłokę. Zmienne te pozwalają na dostęp do argumentów skryptu, informacji o procesie, kodów wyjścia i innych danych kontekstowych.

7.1 Parametry pozycyjne

Parametry pozycyjne przechowują argumenty przekazane do skryptu lub funkcji. Indeksowanie zaczyna się od 1 (nie od 0), a specjalna zmienna $0 zawiera nazwę skryptu.

# Skrypt: args.sh #!/bin/bash # Wywołanie: ./args.sh arg1 arg2 arg3 echo "Nazwa skryptu: $0" echo "Pierwszy argument: $1" echo "Drugi argument: $2" echo "Trzeci argument: $3" echo "Dziesiąty argument: ${10}" # Wynik wywołania: ./args.sh plik.txt kopia.log /backup Nazwa skryptu: ./args.sh Pierwszy argument: plik.txt Drugi argument: kopia.log Trzeci argument: /backup

7.2 Zmienne specjalne

Oprócz parametrów pozycyjnych, Bash udostępnia szereg zmiennych specjalnych z predefiniowanym znaczeniem:

# $# - liczba argumentów echo "Liczba argumentów: $#" # $@ - wszystkie argumenty jako osobne słowa for arg in "$@"; do echo "Argument: $arg" done # $* - wszystkie argumenty jako pojedyncze słowo echo "Wszystkie: $*" # $$ - PID bieżącego procesu (skryptu) echo "PID: $$" # $! - PID ostatniego procesu uruchomionego w tle sleep 60 & echo "PID procesu w tle: $!" # $? - kod wyjścia ostatniego polecenia ls /etc/passwd echo "Kod wyjścia: $?" 0 (sukces) ls /etc/nieistniejacy echo "Kod wyjścia: $?" 2 (błąd) # $- - bieżące opcje powłoki echo "Opcje powłoki: $-"

7.3 Rozszerzenia parametrów

Bash oferuje zaawansowane mechanizmy rozszerzania parametrów, które pozwalają na operacje takie jak wartości domyślne, warunkowe przypisania, manipulacje ciągami i wiele innych.

# Wartość domyślna jeśli zmienna jest pusta lub nieustawiona $ echo ${ZMIENNA:-"domyślna"} domyślna # Przypisz wartość domyślną jeśli zmienna jest pusta $ echo ${ZMIENNA:="nowa"} nowa $ echo $ZMIENNA nowa # Długość zmiennej $ TEKST="Ala ma kota" $ echo ${#TEKST} 11 # Wycinanie prefixu i suffixu $ PLIK="/home/user/dokument.txt" $ echo ${PLIK##*/} # usuń najdłuższy prefix */ = dokument.txt $ echo ${PLIK%/*} # usuń najkrótszy suffix /* = /home/user $ echo ${PLIK:5:4} # substring od 5, długość 4 = /use
9/16 8. Tablice w Bash

Bash wspiera tablice jednowymiarowe (indeksowane liczbami) oraz tablice asocjacyjne (indeksowane ciągami znaków, dostępne od Bash 4). Tablice pozwalają na przechowywanie wielu wartości pod jedną nazwę i są niezastąpione przy przetwarzaniu list danych.

8.1 Deklaracja i operacje na tablicach

Tablice w Bash można tworzyć na wiele sposobów: przez bezpośrednie przypisanie listy wartości, przez przypisanie pojedynczych elementów lub przez deklarację z użyciem declare.

8.1 Deklaracja i operacje na tablicach

Tablice w Bash można tworzyć na wiele sposobów: przez bezpośrednie przypisanie listy wartości, przez przypisanie pojedynczych elementów lub przez deklarację z użyciem declare.

# Tworzenie tablicy $ MOJA_TABLICA=(element1 element2 element3) $ echo "${MOJA_TABLICA[0]}" element1 $ echo "${MOJA_TABLICA[@]}" element1 element2 element3 # Indeksowanie tablicy $ MOJA_TABLICA[5]="element o indeksie 5" $ echo "${MOJA_TABLICA[5]}" element o indeksie 5 # Liczba elementów tablicy $ echo "${#MOJA_TABLICA[@]}" 4 # Długość elementu o danym indeksie $ echo "${#MOJA_TABLICA[0]}" 8 # Dodawanie elementów $ MOJA_TABLICA+=(nowy1 nowy2) $ echo "${MOJA_TABLICA[@]}" element1 element2 element3 element o indeksie 5 nowy1 nowy2 # Usunięcie elementu $ unset MOJA_TABLICA[1] $ echo "${MOJA_TABLICA[@]}" element1 element3 element o indeksie 5 nowy1 nowy2

8.2 Tablice asocjacyjne

Tablice asocjacyjne (słowniki) pozwalają na indeksowanie elementów ciągami znaków zamiast liczbami. Wymagają deklaracji z użyciem declare -A i są dostępne w Bash w wersji 4 i nowszych.

# Deklaracja tablicy asocjacyjnej $ declare -A KONTYNENTY $ KONTYNENTY[Polska]="Europa" $ KONTYNENTY[Japonia]="Azja" $ KONTYNENTY[Brazylia]="Ameryka Południowa" # Dostęp do elementów $ echo "${KONTYNENTY[Polska]}" Europa # Lista wszystkich kluczy $ echo "${!KONTYNENTY[@]}"
10/16 9. Zasięg zmiennych w praktyce

Zrozumienie zasięgu zmiennych jest kluczowe dla pisania poprawnych skryptów. W tej sekcji omówiono praktyczne aspekty zarządzania zasięgiem, w tym hierarchię, dziedziczenie i techniki przekazywania wartości między zakresami.

9.1 Hierarchia zasięgów

W powłoce Bash można wyróżnić następujące poziomy zasięgu, uporządkowane od najszerszego do najwęższego: zmienne środowiskowe (widoczne dla wszystkich procesów), zmienne globalne skryptu (widoczne w całym skrypcie), zmienne lokalne funkcji (widoczne tylko w danej funkcji).

# Demonstracja hierarchii zasięgów #!/bin/bash # Zmienna globalna skryptu GLOBALNA="Jestem globalna" funkcja_zewnetrzna() { echo "Funkcja zewnętrzna widzi: $GLOBALNA" funkcja_wewnetrzna } funkcja_wewnetrzna() { local LOKALNA="Jestem lokalna" echo "Funkcja wewnętrzna widzi: $GLOBALNA i $LOKALNA" echo "Ale nie widzi zmiennej_z_funkcji_zewnetrznej: ${zmienna_zewnetrzna:-'nie istnieje'}" } funkcja_zewnetrzna Funkcja zewnętrzna widzi: Jestem globalna Funkcja wewnętrzna widzi: Jestem globalna i Jestem lokalna Ale nie widzi zmiennej_z_funkcji_zewnetrznej: nie istnieje

9.2 Zmienne środowiskowe a podpowłoki

Uruchomienie polecenia w podpowłoce (za pomocą nawiasów okrągłych lub bash -c) tworzy nowy proces z własną kopią środowiska. Zmiany w podpowłoce nie wpływają na proces macierzysty.

# Podpowłoka z (nawiasy) $ ZMIENNA="przed" $ ( ZMIENNA="zmieniona_w_podpowłoce"; echo $ZMIENNA ) zmieniona_w_podpowłoce $ echo $ZMIENNA przed # Użycie export dla dziedziczenia przez podpowłokę $ export ZMIENNA $ ( echo $ZMIENNA ) przed # Użycie subshella do izolacji zmian $ ( cd /tmp && pwd ) $ pwd /home/użytkownik (katalog nie został zmieniony!)

9.3 Przekazywanie wartości między zakresami

Aby przekazać wartość zmiennej lokalnej na zewnątrz funkcji lub podpowłoki, można użyć kilku technik: echo z subshell i przechwyceniem wyjścia, przekazanie przez zmienną globalną lub przekazanie przez referencję (dostępne w Bash 4+).

# Technika 1: Przechwycenie wyjścia funkcji funkcja_oblicz() { local a=5 local b=3 echo $((a + b)) } WYNIK=$(funkcja_oblicz) $ echo $WYNIK 8 # Technika 2: Przekazanie nazwy zmiennej do ustawienia (nameref) funkcja_przypisz() { local -n ref=$1 ref="nowa_wartość" } ZMIENNA="stara_wartość" funkcja_przypisz ZMIENNA $ echo $ZMIENNA nowa_wartość # Technika 3: Przekazanie przez eval (dla starszych Bash) funkcja_eval() { local nazwa=$1 local wartosc=$2 eval "$nazwa='$wartosc'" } funkcja_eval MOJA_ZMIENNA "wartość_z_funkcji" $ echo $MOJA_ZMIENNA wartość_z_funkcji
11/16 10. Konfiguracja zmiennych - pliki systemowe i użytkownika

Zmienne środowiskowe w Linux są definiowane w różnych plikach konfiguracyjnych, które są wczytywane w określonej kolejności przy logowaniu lub uruchomieniu powłoki. Zrozumienie tej kolejności jest kluczowe dla prawidłowej konfiguracji środowiska.

10.1 Pliki systemowe

Pliki systemowe definiują zmienne dla wszystkich użytkowników systemu i są wczytywane przy logowaniu lub uruchomieniu interaktywnej powłoki.

# /etc/environment - zmienne dla wszystkich sesji # Format: NAZWA=wartość (bez export!) JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 MAVEN_HOME=/opt/maven EDITOR=/usr/bin/nano # /etc/profile - skrypt dla wszystkich użytkowników (logowanie) # Dodaj PATH dla wszystkich: export PATH="$PATH:/opt/moje_narzedzia" # /etc/bash.bashrc - dla interaktywnych powłok Bash # Aliasy i funkcje dla wszystkich: alias ll='ls -la' export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "

10.2 Pliki użytkownika

Pliki w katalogu domowym użytkownika pozwalają na personalizację środowiska bez wpływu na innych użytkowników.

# ~/.bash_profile - wykonywany przy logowaniu powłoki logowania # Zazwyczaj wczytuje ~/.bashrc: if [ -f ~/.bashrc ]; then . ~/.bashrc fi # Dodatkowe ustawienia logowania: export PATH="$PATH:$HOME/.local/bin" # ~/.bashrc - wykonywany dla interaktywnych powłok nielogowania # Aliasy: alias gs='git status' alias ..='cd ..' alias ...='cd ../..' # Funkcje: mkcd() { mkdir -p "$1" && cd "$1"; } # Zmienne użytkownika: export EDITOR="vim" export VISUAL="vim" # ~/.profile - alternatywa dla ~/.bash_profile # Używany gdy ~/.bash_profile nie istnieje

10.3 Kolejność wczytywania plików

Kolejność wczytywania plików konfiguracyjnych zależy od typu uruchomionej powłoki i jej trybu działania. Zrozumienie tej kolejności pozwala na świadome umieszczanie konfiguracji w odpowiednich plikach.

# Powłoka logowania (np. ssh, login w terminalu): 1. /etc/profile 2. ~/.bash_profile, ~/.bash_login lub ~/.profile (pierwszy istniejący) # Powłoka interaktywna nielogowania (np. nowa karta terminala): 1. /etc/bash.bashrc 2. ~/.bashrc # Powłoka nieinteraktywna (skrypty): - Wczytuje tylko zmienne z #!/bin/bash -l lub jawnie źródłowane # Polecenie source - wczytanie pliku w bieżącej powłoce: $ source ~/.bashrc $ . ~/.bash_aliases
12/16 11. Operacje na ciągach tekstowych

Bash oferuje bogaty zestaw operacji na ciągach tekstowych, od prostego wycinania substringów po zaawansowane wzorce. Te operacje są wykonywane bezpośrednio na zmiennych, bez potrzeby używania zewnętrznych poleceń jak sed czy awk.

11.1 Wycinanie substringów

Operacje wycinania pozwalają na pobranie części ciągu znaków na podstawie pozycji lub wzorca.

# Podstawowe wycinanie $ TEKST="Ala ma kota" $ echo ${TEKST:0:3} # od pozycji 0, długość 3 Ala $ echo ${TEKST:4} # od pozycji 4 do końca ma kota $ echo ${TEKST: -4} # 4 ostatnie znaki (spacja przed -!) kota # Usuwanie prefixu i suffixu $ PLIK="/home/user/dokument.txt" $ echo ${PLIK##*/} # najdłuższy prefix */ = dokument.txt $ echo ${PLIK#*/} # najkrótszy prefix */ = home/user/dokument.txt $ echo ${PLIK%%/*} # najdłuższy suffix */ = (puste) $ echo ${PLIK%/*} # najkrótszy suffix */ = /home/user

11.2 Wyszukiwanie i zamiana

Bash pozwala na wyszukiwanie wzorców i zamianę fragmentów ciągów bezpośrednio w rozszerzeniu parametrów.

# Zamiana pierwszego wystąpienia $ TEKST="ala ma kota, kot jest biały" $ echo ${TEKST/kota/psa} ala ma psa, kot jest biały # Zamiana wszystkich wystąpień $ echo ${TEKST//kot/pies} ala ma piesa, pies jest biały # Zamiana prefixu lub suffixu $ TEKST="/home/user/file.txt" $ echo ${TEKST/#\/home/\/tmp} # jeśli prefix /home, zamień na /tmp /tmp/user/file.txt $ echo ${TEKST/%.txt/.bak} # jeśli suffix .txt, zamień na .bak /home/user/file.bak # Warunkowe przypisanie $ echo ${NIEISTNIEJACA:-"wartość domyślna"} wartość domyślna $ ISTNIEJACA="jutro" $ echo ${ISTNIEJACA:-"wartość domyślna"} jutro
13/16 12. Przekazywanie zmiennych między skryptami

Skrypty często muszą komunikować się ze sobą, wymieniając dane lub wyniki. Istnieje kilka standardowych mechanizmów takiej komunikacji w środowisku Linux.

12.1 Eksport i dziedziczenie

Najprostszym mechanizmem jest eksport zmiennej, która zostanie odczytana przez skrypt potomny. Jednak eksport działa tylko w jedną stronę - od rodzica do potomka.

# Skrypt nadrzędny #!/bin/bash export MOJA_WARTOSC="dane_z_rodzica" ./skrypt_potomny.sh # Skrypt potomny (skrypt_potomny.sh) #!/bin/bash echo "Otrzymana wartość: $MOJA_WARTOSC" Otrzymana wartość: dane_z_rodzica

12.2 Przekazywanie przez plik

Dla bardziej złożonych danych lub komunikacji w obie strony, można użyć plików tymczasowych. Skrypt źródłowy zapisuje dane, skrypt docelowy je odczytuje.

# Skrypt A - zapisuje dane do pliku #!/bin/bash echo "WYNIK=obliczona_wartość" > /tmp/wynik$$.txt echo "TIMESTAMP=$(date +%s)" >> /tmp/wynik$$.txt ./skrypt_b.sh # Skrypt B - odczytuje dane z pliku #!/bin/bash source /tmp/wynik$$.txt $ echo "Otrzymany wynik: $WYNIK" Otrzymany wynik: obliczona_wartość $ rm /tmp/wynik*.txt

12.3 Przekazywanie przez argumenty

Argumenty wiersza poleceń są najczęściej używanym mechanizmem przekazywania danych do skryptów. Można je przekazywać bezpośrednio lub w bardziej zaawansowany sposób.

# Wywołanie z argumentami ./skrypt.sh "wartość1" "wartość2" --opcja # Przekazywanie wszystkich argumentów skrypt1.sh "arg1" "arg2" # skrypt1.sh wywołuje skrypt2.sh z tymi samymi argumentami: ./skrypt2.sh "$@" # Przekazywanie przez eval (dynamiczne wywołanie) POLECENIE="./skrypt.sh --flag value" eval $POLECENIE
14/16 13. Najlepsze praktyki i wzorce

Profesjonalne skrypty Bash wymagają stosowania sprawdzonych praktyk, które zapewniają ich niezawodność, czytelność i przenośność. Niżej przedstawiono kluczowe zasady i wzorce.

13.1 Szablon profesjonalnego skryptu

Każdy profesjonalny skrypt powinien rozpoczynać się od shebang, deklaracji opcji powłoki, komentarza z metadanymi oraz inicjalizacji środowiska.

#!/bin/bash # ================================================================= # Skrypt: backup.sh # Autor: Admin # Data: 2026-03-26 # Opis: Automatyczna kopia zapasowa danych # ================================================================= # Wymuszenie natychmiastowego zakończenia przy błędzie set -e # Traktowanie niezdefiniowanych zmiennych jako błędów set -u # Błąd w potoku zwraca błąd set -o pipefail # Wyłączenie globbing dla wzorców set -f # Ścieżka do katalogu skryptu SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Stałe konfiguracyjne readonly LOG_FILE="/var/log/backup.log" readonly KATALOG_ZRODLOWY="/home/dane" # Funkcja logowania loguj() { local poziom=$1 shift echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$poziom] $*" | tee -a "$LOG_FILE" } # Obsługa błędów trap 'loguj "ERROR" "Linia $LINENO: $BASH_COMMAND"; exit 1' ERR # Główna logika skryptu...

13.2 Konwencje nazewnictwa

Stosowanie spójnych konwencji nazewnictwa znacząco poprawia czytelność kodu i ułatwia jego utrzymanie.

# Stałe - WIELKIE_LITERY_Z_PODKREŚLNIKAMI readonly KATALOG_KONFIGURACJI="/etc/app" readonly MAKSYMALNA_LICZBA_PROB=3 # Zmienne globalne skryptu - WIELKIE_LITERY ILOSC_PLIKOW=0 KOD_BLEDU=0 # Zmienne lokalne - male_litery_z_podkreslnikami lokalna_funkcja() { local plik_tymczasowy="" local licznik_elementow=0 local wynik_operacji="" } # Funkcje - nazwy_czy_slowa_z_podkreslnikami inicjalizuj_srodowisko() { ... } sprawdz_wymagania() { ... } wykonaj_kopie_zapasowa() { ... } # Tablice - nazwa w liczbie mnogiej z _LIST lub _ARRAY declare -a PLIKI_DO_KOPII declare -A USTAWIENIA_SRODOWISKA

13.3 Walidacja zmiennych

Zawsze waliduj zmienne przed ich użyciem, szczególnie w kontekście operacji krytycznych jak dostęp do plików czy modyfikacja systemu.

# Funkcja sprawdzająca czy zmienna jest ustawiona czy_ustawiona() { local nazwa=$1 [[ -z "${!nazwa:-}" ]] && return 1 || return 0 } if ! czy_ustawiona "KATALOG_ZRODLOWY"; then echo "BŁĄD: KATALOG_ZRODLOWY nie jest ustawiony!" >&2 exit 1 fi # Walidacja ścieżki do katalogu if [[ ! -d "$KATALOG_ZRODLOWY" ]]; then echo "BŁĄD: Katalog '$KATALOG_ZRODLOWY' nie istnieje!" >&2 exit 1 fi # Walidacja wartości numerycznej if ! [[ "$WARTOSC" =~ ^[0-9]+$ ]]; then echo "BŁĄD: '$WARTOSC' nie jest liczbą!" >&2 exit 1 fi
15/16 14. Typowe błędy i jak ich unikać

Znajomość typowych błędów i pułapek związanych ze zmiennymi w Bash pozwala na szybsze debugowanie i pisanie bardziej niezawodnego kodu.

14.1 Problemy z cudzysłowami

Brak cudzysłowów wokoło zmiennych może prowadzić do nieoczekiwanych zachowań, szczególnie gdy wartość zawiera spacje lub inne znaki specjalne.

# BŁĄD: brak cudzysłowów $ PLIK="plik z spacjami.txt" $ ls $PLIK ls: cannot access 'plik': No such file or directory # POPRAWNIE: z cudzysłowami $ ls "$PLIK" plik z spacjami.txt # Prawidłowe testy z cudzysłowami $ if [[ -f "$PLIK" ]]; then echo "Plik istnieje" fi

14.2 Problemy z niezdefiniowanymi zmiennymi

W Bash zmienne niezdefiniowane są traktowane jako puste ciągi, co może prowadzić do subtelnych błędów. Opcja set -u wymusza błąd przy użyciu niezdefiniowanej zmiennej.

# BŁĄD: użycie niezdefiniowanej zmiennej $ set -u $ echo $NIEOKRESLONA bash: NIEOKRESLONA: unbound variable # POPRAWNIE: użyj wartości domyślnej $ echo "${NIEOKRESLONA:-pusty}" pusty # POPRAWNIE: przypisz wartość domyślną $ : ${DOMYŚLNA:="wartość"} $ echo $DOMYŚLNA wartość

14.3 Problemy z operatorami porównania

W Bash istnieją różne operatory porównania dla liczb i ciągów. Użycie niewłaściwego operatora prowadzi do nieoczekiwanych wyników.

# BŁĄD: użycie operatora numerycznego dla ciągów $ [[ "10" > "2" ]] && echo "10 > 2" || echo "10 <= 2" 10 <= 2 (BŁĄD! Porównanie leksykograficzne!) # POPRAWNIE: użyj -gt dla liczb $ [[ 10 -gt 2 ]] && echo "10 > 2" || echo "10 <= 2" 10 > 2 # POPRAWNIE: dla ciągów użyj > (alfabetyczne) $ [[ "jabłko" > "banan" ]] && echo "jabłko > banan" jabłko > banan # Użycie (( )) dla wyrażeń arytmetycznych $ if (( 10 > 2 )); then echo "10 > 2"; fi 10 > 2
16/16 15. Podsumowanie

Zmienne w systemach Linux stanowią fundamentalny mechanizm konfiguracji środowiska, przechowywania danych i komunikacji między procesami. Zrozumienie architektury zmiennych - od systemowych poprzez użytkownika, aż po lokalne zmienne skryptów i funkcji - jest niezbędne dla każdego, kto pracuje z linią poleceń lub pisze skrypty automatyzujące zadania.

Pamiętaj o fundamentalnych zasadach: zawsze używaj cudzysłowów wokoło zmiennych zawierających ścieżki lub tekst z białymi znakami, stosuj local wewnątrz funkcji dla zmiennych tymczasowych, eksportuj tylko te zmienne, które muszą być widoczne dla procesów potomnych, używaj set -u i set -e dla lepszego zarządzania błędami, stosuj spójne nazewnictwo i dokumentuj swoje skrypty. Przestrzeganie tych zasad znacząco zwiększy jakość i niezawodność Twoich skryptów powłoki w środowisku Linux.