Dydaktyka:
FeedbackTo jest stara wersja strony!
Zmienne środowiskowe
(Environment variables)
to powiązany z procesem zbiór par nazwa – wartość.
Nazwy zmiennych nie mogą zawierać znaku =
i powinny zawierać tylko litery
(z zakresu ASCII), cyfry i podkreślnik, oraz powinny zaczynać się od litery.
Częstym stylem jest używanie tylko znaków A-Z
, _
i 0-9
w nazwach
zmiennych.
Każdy proces ma osobny zbiór zmiennych środowiskowych.
Tworząc nowy proces
można wybrać czy kopiuje wszystkie zmienne środowiskowe rodzica, czy kopiuje
inny podany zbiór zmiennych.
Powłoka dzieli swoje zmienne środowiskowe na te które zostaną przekazane
procesom potomnym (eksportowane) i te, które nie będą przekazane procesom
potomnym.
Zmienne środowiskowe nie są pomysłem powłoki, tylko systemu operacyjnego.
Ustawienie wartości zmiennej (i stworzenie jej, jeśli wcześniej nie istniała):
NAZWA=wartość
Uwaga: NAZWA =wartość
spróbuje uruchomić program NAZWA
z argumentem
=wartość
.
Uwaga: NAZWA = wartość
spróbuje uruchomić program NAZWA
z argumentami
=
oraz wartość
.
Uwaga: NAZWA= wartość
spróbuje uruchomić program wartość
przekazując
mu wśród zmiennych środowiskowych zmienną NAZWA
z pustą wartością.
Do usunięcia zmiennej należy wykorzystać polecenie unset NAZWA
.
Uwaga: zwykle w powłoce pusta zmienna i nieustawiona zmienna zachowują się
identycznie
Domyślnie nowo tworzone zmienne nie są przekazywane do procesów potomnych.
Aby ustawić przekazywanie zmiennej środowiskowej o nazwie NAZWA
do
procesów potomnych, należy wykonać:
export NAZWA
lub, aby jednocześnie ustawić przekazywanie do procesów potomnych i wartość:
export NAZWA=wartość
Uwaga: można wyeksportować jeszcze nieistniejącą zmienną i później ją
stworzyć.
POSIX nie przewiduje cofnięcia eksportu zmiennej; można ją co najwyżej usunąć
komendą unset NAZWA
i ustawić na nowo jako zwykłą nieeksportowaną
zmienną.
Bash pozwala na cofnięcie eksportowania zmiennej przez export -n NAZWA
.
Aby zobaczyć listę wszystkich zmiennych środowiskowych, należy wykonać komendę
set
1).
Aby zobaczyć listę eksportowanych zmiennych środowiskowych, należy
wykonać komendę env
2).
Aby powłoka wstawiła w podane miejsce wartość zmiennej o nazwie NAZWA
,
należy wpisać $NAZWA
.
Np: jeśli wartość zmiennej $UID
to 1000, to cd /run/user/$UID/
wejdzie
do katalogu /run/user/1000/
a polecenie echo $NAZWA
wyświetli wartość
zmiennej NAZWA
.
user@host ~ $ X=5 user@host ~ $ Y=tekst user@host ~ $ Z="ala ma kota" user@host ~ $ echo $Z $Y$X.txt ala ma kota tekst5.txt user@host ~ $ E=echo user@host ~ $ $E $Z > $Y$X.txt user@host ~ $ cat tekst5.txt ala ma kota user@host ~ $ export W=słowo user@host ~ $ export Y user@host ~ $ echo "W='$W' X='$X' Y='$Y' Z='$Z'" W='słowo' X='5' Y='tekst' Z='ala ma kota' user@host ~ $ sh sh-5.1$ echo "W='$W' X='$X' Y='$Y' Z='$Z'" W='słowo' X='' Y='tekst' Z='' sh-5.1$ Y="inny_tekst" sh-5.1$ echo "W='$W' X='$X' Y='$Y' Z='$Z'" W='słowo' X='' Y='inny_tekst' Z='' sh-5.1$ exit exit user@host ~ $ echo "W='$W' X='$X' Y='$Y' Z='$Z'" W='słowo' X='5' Y='tekst' Z='ala ma kota'
PATH | Lista oddzielonych dwukropkami ścieżek w których będą szukane programy Np. żeby wykonać komendę ls , powłoka szuka pliku o nazwie ls w ścieżkach z PATH |
HOME | Katalog domowy bieżącego użytkownika |
PS1 PS2 | Podstawowy znak zachęty (prompt) Znak zachęty dla kolejnych linii komendy |
PWD | Bieżący katalog roboczy |
EDITOR | Domyślny edytor tekstowy Np. less przy otwarciu pliku do edycji skrótem v uruchamia $EDITOR ścieżka_do_pliku |
LOGNAME / USER UID | Nazwa bieżącego użytkownika Numeryczny identyfikator bieżącego użytkownika |
LANG | Język, region i kodowanie znaków; dla Polski zwykle pl_PL.UTF-8 np. de_CH.UTF-8 oznacza niemiecki, Szwajcarię i kodowanie UTF-8 |
TERM | Nazwa terminala określająca jego techniczne możliwości, takie jak ilość wspieranych kolorów, możliwość przesuwania kursora wstecz etc. Więcej w man 7 term (wersja online). |
COLUMNS LINES | Liczba znaków mieszczący się na ekranie w wierszu (=kolumn) Liczba wierszy (linii tekstu) mieszczących się na ekranie |
RANDOM | Losowa liczba (generowana na nowo przy każdym odwołaniu się do zmiennej) |
Więcej w dokumentacji Basha i standardzie POSIX .
Zadanie 1 Ustaw zmienną o nazwie VAR
a następnie wyświetl jej wartość.
Zadanie 2 Ustaw zmienną o nazwie OTHER
na wartość zmiennej VAR
.
Wypisz wartość OTHER
Zadanie 3 Ustaw wartość zmiennej PROG
na ls
, oraz wartość
zmiennej ARG
na /tmp
. Następnie wpisz w powłokę $PROG $ARG
.
Zadanie 4 Wyświetl wartości zmiennych z tabeli powyżej.
Zadanie 5 Zmień wartość zmiennej LANG
na ja_JP.UTF-8
i uruchom program date
oraz vim
.
Zmień wartość zmiennej LANG
na de_DE.UTF-8
i spróbuj wykonać rm -rf /root/.ssh/nope
oraz lscpu
.
Zadanie 6 Zmień wartość zmiennej PS1
.
Zadanie 7 Spróbuj wykonać komendę lspci
. Zmień wartość zmiennej PATH
tak, żeby zawierała ścieżki /sbin
i /usr/sbin
. Ponownie spróbuj wykonać
komendę lspci
.
Działanie powłoki (wg. POSIX, wg. podręcznika Basha):
1. czyta linię | echo ${Y} "$Z 2+3=$((2+3))" > file; ls baz |
2. rozbija ją na tokeny i rozwiązuje aliasy | echo , ${Y} , "$Z 2+3=$((2+3))" , > , file , ; , ls , --color=auto , baz |
3. dzieli na komendy | echo , ${Y} , "$Z 2+3=$((2+3))" , > , file |
4. wykonuje podstawienia | echo , a , b , c d 2+3=5 , > , file |
5. ustawia przekierowania | echo , a , b , c d 2+3=5 |
6. uruchamia komendę |
Polecenia można oddzielać przez:
;
– cmd ; …
wykonana cmd
i przejdzie dalej&
– cmd & …
uruchomi w tle cmd
i przejdzie dalej&&
– a && b
wykona a
i jeśli a
zakończy się powodzeniem, uruchomi b
a
i b
zakończą się powodzeniem||
– a || b
wykona a
i jeśli a
zakończy się błędem, uruchomi b
a
i b
zakończą się błędemPolecenia można grupować przez:
{ … }
– grupuje polecenia w tej powłoce, { … }
muszą być zakończone przez ;
lub &
(…)
– uruchamia polecenia w osobnej powłoce ("podpowłoce").Przykłady:
{ cd /tmp; pwd; }; pwd
– wejdzie do /tmp
i wypisze dwa razy katalog roboczy /tmp
(cd /tmp; pwd); pwd
– uruchomi podpowłokę w której wejdzie do /tmp
, wypisze katalog roboczy /tmp
w podpowłoce i wypisze bieżący katalog roboczy (np. katalog domowy) w powłoce
user@host ~ $ echo one; echo two one two user@host ~ $ time sleep 0.1 & echo three [1] 8222 three user@host ~ $ real 0m0,102s user 0m0,000s sys 0m0,001s [1]+ Zakończono time sleep 0.1 user@host ~ $ grep --quiet user /etc/passwd && echo "found" || echo "missing" found user@host ~ $ grep --quiet alien /etc/passwd && echo "found" || echo "missing" missing user@host ~ $ (cd /run/user/ && pwd && ls -l); pwd /run/user razem 0 drwx------ 10 user students 280 05-08 11:11 1000 /home/user user@host ~ $ { uname; date -d @0;}|rev xuniL TEC 00:00:10 ,0791 yts 1 ,wzc user@host ~ $
Zadanie 8 Napisz polecenie które spróbuje usunąć plik plik
i jeśli
to się uda, to wyświetli udało się
Zadanie 9 Napisz polecenie które spróbuje usunąć plik plik
i jeśli
to się nie uda, to wyświetli nie udało się
Zadanie 10 Policz łączną ilość znaków w wynikach poleceń uname -a
oraz date
.
Zadanie 11 Ustaw zmienną środowiskową wewnątrz (…)
i wyświetl jej wartość
po wykonaniu (…)
.
Następnie powtórz zadanie dla { … }
.
Zadanie 12 Uruchom w tle grupę poleceń która za pięć sekund wykona program
fortune
.
Podstawienia (shell expansion / word expansion) polegają na zastąpieniu tekstu (pasującego do konkretnego wzorca) przez określoną wartość (wg. POSIX, wg. podręcznika Basha).
Dostępne podstawienia (w kolejności wykonywania przez BASH):
{…}
– zakres lub lista (Uwaga: POSIX nie definiuje tego podstawienia, jest ono dostępne w Bashu i niektórych innych powłokach)~
i ~username
– katalog domowy${…}
– zmienna / parametr$((…))
– arytmetyka (POSIX wymaga tylko wsparcia dla arytmetyki całkowitoliczbowej)$(…)
i `…`
– podstawia wynik komendy*
, ?
i […]
) – dopasowuje nazwy plików (było na pierwszych zajęciach)
Wewnątrz podwójnych cudzysłowów są wykonywane tylko podstawienia zaczynające się
od $
oraz `
.
Wewnątrz pojedynczych cudzysłowów nie są wykonywane żadne podstawienia.
W Bashu funkcjonują też cudzysłowy $'…'
które pozwalają na
wprowadzanie sekwencji poprzedzanych przez odwrócony ukośnik takich jak np.
\n
; patrz
dokumentacja Basha.
Jeśli wyniki podstawienia (poza dopasowaniem nazw plików) zawierają spację i nie
są wewnątrz cudzysłowów, to ich wynik jest rozbijany na osobne tokeny (słowa).
Np: ls $(echo dwa słowa)
spróbuje wypisać katalog dwa
i katalog
słowa
, a ls "$(echo dwa słowa)"
spróbuje wypisać katalog dwa słowa
liczby (lub litery) z podanego zakresu format: {początek..koniec..krok} | {1..5} | 1 2 3 4 5 |
file{15..20}.txt | file15.txt file16.txt file17.txt file18.txt |
|
{0..9..3} | 0 3 6 9 |
|
{a..z..2} | a f k p u z |
|
wymienione po przecinkach elementy format: {element1,element2,…} | {a,b,d,f} | a b d f |
/tmp/{ala,ma,kota}.txt | /tmp/ala.txt /tmp/ma.txt /tmp/kota.txt |
|
file{,.gz,.bzip2,.xz} | file file.gz file.bzip2 file.xz |
Zadanie 13 Stwórz puste pliki plik_1
, plik_2
, ..., plik_9
(używając nawiasów wąsatych do stworzenia listy plików).
Zadanie 14 Przeanalizuj co robi polecenie: echo -e " " {A..H} '\n'{8..1}
Zadanie 15 Wykonaj komendę stat
dla plików /var/log/btmp
,
/var/log/mtmp
, /var/log/wtmp
(używając nawiasów wąsatych do stworzenia
listy plików).
katalog domowy bieżącego użytkownika | ~ | /home/username |
katalog domowy użytkownika username | ~username | /home/username |
Zadanie 16
Wypisz ścieżkę do swojego katalogu domowego korzystając z ~
.
Zadanie 17
Wejdź do katalogu domowego użytkownika wwwrun
.
Poza podstawianiem wartości zmiennej przez $ZMIENNA
można też użyć składni
${ZMIENNA}
. Pozwala to np., na napisanie ${SIZE}MB
.
Wyrażenie ${#ZMIENNA}
podstawia długość (ilość znaków) zmiennej.
Np. X='żółć'; echo ${#X}
wypisze 4
.
Dodając za nazwą zmiennej, ale wewnątrz nawiasów modyfikatory, można uzyskać:
${X:-wyrażenie}
– podstawia wartość X
lub, jeśli X
nie istnieje lub jest puste, podstawia wartość wyrażenie
${X:+wyrażenie}
– podstawia wartość wyrażenie
jeśli X
ma niepustą wartość, inaczej podstawia pustą wartość${X:liczba}
– podstawia wartość X
pomijając liczba
znaków${X::liczba}
– podstawia pierwsze liczba
znaków z wartości X
${X:ile_pominąć:ile_wypisać}
– podstawia pierwsze ile_wypisać
znaków z wartości X
zaczynając od znaku ile_pominąć+1
${X%wzorzec}
– ucina z końca najkrótsze dopasowanie do wzorzec
(o ile takie jest) ${X%%wzorzec}
– ucina z końca najdłuższe dopasowanie do wzorzec
(o ile takie jest)${X#wzorzec}
– ucina z początku najkrótsze dopasowanie do wzorzec
(o ile takie jest) ${X##wzorzec}
– ucina z początku najdłuższe dopasowanie do wzorzec
(o ile takie jest)${X/wzorzec/wyrażenie}
– zamienia pierwsze wystąpienie wzorzec
przez wyrażenie
${X//wzorzec/wyrażenie}
– zamienia wszystkie wystąpienia wzorzec
przez wyrażenie
${X/…}
i ${X//…}
są rozszerzeniem Basha
user@host ~ $ F="/home/user/.local/share/okular/docdata/3882215.main document.pdf.xml" user@host ~ $ echo "$F" /home/user/.local/share/okular/docdata/3882215.main document.pdf.xml user@host ~ $ echo "$F_bak" # Odczytuje wartość (nieistniejącej) zmiennej F_bak user@host ~ $ echo "${F}_bak" /home/user/.local/share/okular/docdata/3882215.main document.pdf.xml_bak user@host ~ $ echo "${F##*/}_bak" 3882215.main document.pdf.xml_bak user@host ~ $ NAME="${F##*/}" user@host ~ $ echo ${NAME} 3882215.main document.pdf.xml user@host ~ $ echo "${NAME%.*}" 3882215.main document.pdf user@host ~ $ echo "${F//\//\\}" # lub "${F//'/'/'\'}" \home\user\.local\share\okular\docdata\3882215.main document.pdf.xml user@host ~ $ HEX=123456789abcdef0 user@host ~ $ echo "${#HEX} : ${HEX::7} - ${HEX:7:2} - ${HEX:9}" 16 : 1234567 - 89 - abcdef0
Zadanie 18 Wpisz do zmiennej FILE
nazwę pliku. Następnie wykonaj
polecenie które zmieni nazwę tego pliku dodając na koniec rozszerzenie .txt
.
Zadanie 19 Czy rozwiązanie poprzedniego zadania zadziała dla nazwy pliku ze spacją? Sprawdź. Jeśli nie - popraw je.
Zadanie 20 Załóż że w zmiennej M
jest numer miesiąca (np. 05
),
a w zmiennej D
jest numer dnia (np. 08
). Wykorzystując te zmienne
przypisz wartość zmiennej LOGFILE
tak, żeby miała postać
myprog_miesiąc_dzień.log
.
Następnie przekieruj wynik polecenia
echo hello world
do wartości tej zmiennej.
Zadanie 21 Napisz komendę, która przeniesie pliki file1
i file2
do katalogu wskazanego w zmiennej TARGET
lub, jeśli ta zmienna jest pusta,
do katalogu /tmp
.
Zadanie 22 Przyjmij, że w zmiennej S
jest pełna ścieżka do pliku
(np. /home/user/some dir/some file.sh
).
Do zmiennej D
przypisz katalog
w którym znajduje się plik wskazany przez S
, a do F
przypisz samą nazwę
pliku wskazanego przez S
.
Następnie wypisz wartość D
oraz S
.
Zadanie 23 Przygotuj komendę która zmienia nazwę pliku wskazanego przez
zmienną F
tak, by nazwa nie zawierała spacji.
Wyrażenia $(cmd)
oraz `cmd`
zostaną zastąpione wynikiem polecenia cmd
.
Trzeba pamiętać że w linii cmd … $(sub) …
najpierw zostanie w całości
wykonane polecenie sub
, a potem jego wynik będzie podstawiony w miejsce
$(sub)
.
Zaleca się używać składni $(cmd)
, składnia `cmd`
jest wspierana
dla kompatybilności wstecznej.
Wyrażenia $(…)
można dowolnie zagnieżdżać
w sobie.
Zadanie 24 Napisz komendę która wyświetli napis
W bieżącym katalogu znajduje się N plików
, gdzie w miejsce N
zostanie wstawiona faktyczna liczba plików.
Zadanie 25 Komenda readlink -f nazwa_pliku
(i realpath nazwa_pliku
)
rozwiązuje wszystkie symlinki i pokazuje kanoniczną ścieżkę do pliku. Przypisz
do zmiennej DIR
kanoniczną ścieżkę do ..
(do katalogu nadrzędnego).
Zadanie 26 Komenda date +%H_%M_%S
wypisuje bieżący czas.
Napisz komendę która przekierowuje wynik programu pstree -au
do pliku
procesy_CZAS.log
, gdzie w miejscu CZAS
ma pojawić się bieżący
czas.
Zadanie 27 Komenda iconv -t ascii//TRANSLIT
zamienia znaki ze
standardowego wejścia (lub wskazanych plików) na kodowanie ASCII, zamieniając
niekodowalne znaki na najbliższe odpowiedniki.
Przygotuj komendę która zmienia nazwę pliku wskazanego przez zmienną F
tak,
by nowa nazwa składała się tylko ze znaków ASCII.
Powłoka wspiera obliczenia (przynajmniej) całkowitoliczbowe.
Standard POSIX definiuje tylko składnię $((…))
.
Bash dodatkowo posiada polecenie let …
wykonujące podane działania.
Wewnątrz $((…))
/ let …
można:
$
przed nazwami zmiennych, np. x=$((x+2))
echo $((y=2**5, z=10^6))
przypisze do y
wartość 25 = 32
, przypisze do z wartość 10 xor 6 = 12
, wyliczy 32, 12 = 12
(operator przecinka z C) i wykona echo 12
$((…))
jest traktowana jakby była w podwójnych cudzysłowach,let …
liczy każdy z argumentów z osobna, X=$(( ( 2 + 2 ) * 2 ))
, let "X = ( 2 + 2 ) * 3"
, let X=(2+2)*3
i let X=(2+2)*3 Y=2*X+1
są poprawne, ale let X = ( 2 + 2 ) * 3
let …
trzeba escape'ować znaki specjalne, np. let X=0xff\&1066
/ let "X = 0xff & 1066"
POSIX standaryzuje też program expr
który wykonuje podane obliczenie i wypisuje jego wynik na standardowe wejście.
Wyżej wymieniona funkcjonalność powłoki / program należy traktować jako narzędzia pomocnicze do pisania skryptów, a nie narzędzia do obliczeń.
Proste, sensowne kalkulatory dla powłoki to np. bc
, calc
i qalc
.
Zadanie 28 Ustaw zmienne X
i Y
na wybrane dwucyfrowe liczby, a następnie:
• zwiększ X
o 1
• zwiększ Y
o 2
• ustaw zmienną Z
na iloczyn X
i Y
• wylicz resztę z dzielenia Z
przez 128.
Zadanie 29 Przygotuj polecenie, które:
• przypisze bieżący czas w nanosekundach (wynik komendy date +%s%N
) do zmiennej START
• wykona komendę sleep 1s
• przypisze bieżący czas w nanosekundach (wynik komendy date +%s%N
) do zmiennej END
• wypisze różnicę między END
a START
Alias (POSIX, Bash) to
słowo, które jeśli wystąpi w miejscu komendy, to zostanie zastąpione wcześniej
ustalonym tekstem.
Przykładowo: wiele dystrybucji Linuksa automatycznie ustawia alias la
na
wartość ls -la
i aliasuje ls
na ls --color=auto
.
Przy takich ustawieniach po wpisaniu la
najpierw następuje zmiana la
na
ls -la
(i wyłączenie dla przetwarzania tego polecenia aliasu la
), potem
ls
na ls --color=auto
(i wyłączenie dla przetwarzania tego polecenia
aliasu ls
).
Aby utworzyć nowy alias, należy wykonać komendę:
alias słowo=na_co_ma_się_tłumaczyć
Np: alias la="ls -la"
Alias można usunąć komendą unalias słowo
.
Wpisanie komendy alias
bez argumentów wypisze wszystkie ustawione aliasy.
Żeby sprawdzić czy dany wyraz co
jest programem, aliasem czy jeszcze
czymś innym, można użyć komendy type co
.
Aliasy, podobnie jak zmienne, są ustawiane dla bieżącej powłoki.
Zadanie 30 Stwórz alias year
który będzie równoważny cal -my
.
Użyj tego aliasu. Użyj tego aliasu żeby wyświetlić kalendarz na rok 2025.