Wprowadzenie do najbardziej przydatnych zmiennych specjalnych i środowiskowych w Bash

Poznaj kluczowe zmienne specjalne i środowiskowe w Bash, które pomogą w pisaniu bardziej efektywnych skryptów, uzyskując dostęp do ważnych informacji systemowych.
Czy obecnie uczysz się Basha? Czy widziałeś takie rzeczy jak $0 i $EUID i zastanawiałeś się, co one oznaczają? Albo jaka jest różnica między $UID a $EUID? Omówię te i inne kwestie: co one robią i dlaczego są ważne.
Specjalne parametry
Specjalne parametry to zmienne dostarczane przez Bash do określonych celów. Jest ich mniej niż 10, a poniższe uważam za najbardziej przydatne.
Uzyskaj ścieżkę skryptu
Czasami, pisząc skrypt, chcesz znać jego ścieżkę. Na przykład, przy tworzeniu menu pomocy, zwykle umieszczasz nazwę skryptu na górze. Oto menu pomocy dla polecenia ls:
ls --helpMożesz uzyskać (względną) ścieżkę, korzystając ze specjalnego parametru $0. To standard POSIX, więc możesz go używać w większości powłok:
echo "$0"Następnie możesz uzyskać nazwę skryptu, używając $(basename $0):
Jednak czasami $0 nie jest niezawodny—na przykład polecenie source /path/to/script.sh zwraca "bash", a nie ścieżkę skryptu. Zamiast tego użyj zmiennej $BASH_SOURCE, która działa niemal identycznie, ale bez niespodzianek. Jeśli używasz tylko Basha, jest to lepszy wybór, ale nie jest przenośny do innych powłok.
Określ status wyjścia procesu
Każdy program zwraca liczbę po zakończeniu. Nazywa się to kodem zakończenia i jest używane do podejmowania decyzji, gdy polecenie zwraca błąd. Na przykład, jeśli spróbujesz użyć ls w nieistniejącym katalogu, zwróci to wartość różną od zera.
Zerowy status wyjścia oznacza sukces; wartość różna od zera wskazuje na problem.
Gdy napotkasz problem, możesz chcieć wstrzymać wykonywanie, a specjalny parametr $? dostarcza niezbędny kod wyjścia:
ls /system32 echo $?Istnieje kilka sposobów wykrywania i obsługi kodu wyjścia. Najbardziej oczywistym rozwiązaniem jest ocena "$?" za pomocą instrukcji warunkowej:
if [[ $? -eq 0 ]]; then fiKod wyjścia zazwyczaj coś oznacza i jest specyficzny dla programu, ale możesz obsługiwać różne wartości przy użyciu instrukcji case:
case $? in 0) echo "OK";; 1) echo "Err";; *) echo "Nieobsługiwany błąd";; esacMoim ulubionym podejściem jest użycie instrukcji warunkowej bez nawiasów:
if ls /system32; then echo "/system32 istnieje" fiLecz najbardziej eleganckim rozwiązaniem jest użycie operatorów logicznych:
ls /system32 && echo "/system32 istnieje" ls /system32 || echo "/system32 nie istnieje"Dostęp do argumentów
Jeśli piszesz skrypt Basha, z pewnością będziesz musiał przekazać mu wartości—znane także jako argumenty lub parametry pozycyjne. Podejście Basha jest trochę nieporęczne, ale działa. Przykłady są najłatwiejszym sposobem ich zrozumienia:
foo() { echo "$1" echo "$2" } foo "pierwszy" "drugi"Przekazałem argumenty do funkcji, ale działają one dokładnie tak samo na najwyższym poziomie twojego skryptu. Na przykład:
#!/usr/bin/env bash echo "Pierwszy argument: $1" echo "Drugi argument: $2"Możesz następnie przekazać argumenty do swojego skryptu za pomocą CLI: script.sh "pierwszy" "drugi".
Przechodząc dalej, specjalny parametr "$@" reprezentuje wszystkie argumenty jako tablicę:
foo() { for arg in "$@"; do echo "$arg" done } foo "pierwszy" "drugi"Specjalny parametr "$*" jest taki sam jak "$@", z tą różnicą, że umieszcza wszystkie argumenty w jednym ciągu (jeśli "$*" ma podwójne cudzysłowy):
at() { printf '@: [%s]\n' "$@" } star() { printf '*: [%s]\n' "$*" } at "jeden dwa" "trzy" star "jeden dwa" "trzy"Możesz zobaczyć, że "$@" wyświetla dwa argumenty w dwóch linijkach, podczas gdy "$*" wyświetla je w jednej.
Aby uzyskać liczbę argumentów, możesz użyć składni ${#@} lub ${#*}:
foo() { echo ${#@} echo ${#*} } foo "jeden" "dwa"Zmienne środowiskowe
Zmienne środowiskowe to wartości przekazywane do działających programów przez powłokę. Na przykład, $HOME podaje ścieżkę do katalogu domowego bieżącego użytkownika.
Uzyskaj ID użytkownika
Od czasu do czasu potrzebuję znać bieżące ID użytkownika w skrypcie. Na przykład, niedawno wchodziłem w interakcję z gniazdem w katalogu /run/user/1000. "1000" to ID użytkownika, a jeśli chcemy, aby skrypt był solidny, nie powinniśmy twardo kodować tej wartości, ponieważ inny użytkownik uruchamiający go może mieć inne ID użytkownika.
Aby to rozwiązać, możemy użyć zmiennych $UID i $EUID. "$UID" wyświetla ID użytkownika uruchamiającego binarny. "$EUID" (efektywne ID użytkownika) to ID użytkownika procesu wykonującego binarny. Zazwyczaj są one równe, ale dla binarnych setuid mogą się różnić. Na przykład, podczas wykonywania czegoś z użyciem sudo, różnią się w miarę postępu forkingu.
ps --forest -eo cmd,euid,ruid | grep -C 1 '[s]udo'Mam "sudo sleep 600" uruchomione w tle, a powyższy prompt wyświetla kolumny komendy, EUID ("1") i UID ("2") dla każdego procesu uruchamiającego sudo. Można zauważyć, że EUID staje się "0" od razu, ale UID nie zmienia się, aż do ostatecznego procesu forkowanego (który jest "sleep" uruchamiane jako root).
Co możemy z tego wyciągnąć? Cóż, tak naprawdę nie ma znaczenia, którego użyjesz. Niektórzy mówią, aby używać "$EUID", aby sprawdzić, czy masz uprawnienia root, ponieważ to efektywne uprawnienia. Jednak z obrazu wynika, że ostateczny proces "sleep" ma ustawione zarówno UID, jak i EUID na "0" (root), a proces powłoki ma oba ustawione na "1000" (użytkownik). Reprezentują one obie strony procesu forkowania - gdzie zainicjowałeś żądanie sudo i również ostateczny proces wykonawczy. Dlatego między nimi nie ma użytecznej różnicy wtedy, kiedy ma to znaczenie, ale pamiętaj, że różnią się dla binarnych setuid podczas procesu forkowania.
Uzyskaj typowe ścieżki użytkownika
Prawie w każdym skrypcie, który piszę, uzyskuję dostęp do katalogu domowego. Rzadziej potrzebuję dostępu do ~/.config lub ~/.local/share. Uzyskiwanie dostępu do typowych lokalizacji w systemie plików jest powszechne, ale twarde kodowanie ścieżek w ten sposób jest złym zwyczajem, ponieważ mogą one ulec zmianie. Zalecanym podejściem jest korzystanie z specyfikacji katalogu XDG, która jest zbiorem standardowych zmiennych dostarczonych przez freedesktop.org.
env | grep XDG | sort -uNie wszystkie zmienne są ustawione, a niektóre nie są ścieżkami.
Kiedy korzystasz ze zmiennych XDG, zawsze ustawiaj sensowny domyślny:
export "${XDG_CACHE_HOME:=$HOME/.cache}"To również ustawi zmienną (jeśli nie jest ustawiona) i udostępni ją wszelkim binarnym lub skryptom, które uruchamiasz.
Najbardziej typowe zmienne, z którymi się spotykam:
export "${XDG_CACHE_HOME:=$HOME/.cache}" export "${XDG_CONFIG_HOME:=$HOME/.config}" export "${XDG_DATA_HOME:=$HOME/.local/share}" Jest ich jeszcze kilka, i zachęcam do ich poznawania. Powinieneś korzystać z tych lokalizacji zamiast pisać wszystko do /tmp lub własnego katalogu w ~/.
Oprócz tych zmiennych, wiele przydatnych zmiennych środowiskowych jest dostępnych przez powłokę. Omówione zmienne to te, które używam najczęściej. Nie mógłbym pisać skryptów Bash bez nich. Z kolei twarde kodowanie wartości ostatecznie doprowadzi do awarii. Kiedy masz setki skryptów, takie awarie stają się koszmarem konserwacyjnym. Dlatego najlepiej jest wnioskować, ile tylko możesz z innego miejsca, najlepiej ze standardowych zmiennych, a zmienne przedstawione dzisiaj spełniają ten warunek.
Na koniec, poznawaj i używaj jak najwięcej standardowych zmiennych.
26
Jeśli ciekawią Cię artykuły podobne do Wprowadzenie do najbardziej przydatnych zmiennych specjalnych i środowiskowych w Bash, zajrzyj do kategorii Linux i odkryj jeszcze więcej interesujących treści.
Dodaj komentarz

Możesz być zainteresowany