Jak śledzić wykonywanie poleceń w skrypcie powłoki za pomocą śledzenia powłoki
W tym artykule z serii debugowania skryptów powłoki wyjaśnimy trzeci tryb debugowania skryptu powłoki, czyli śledzenie powłoki, i przyjrzymy się kilku przykładom, aby zademonstrować, jak to działa i jak można go używać.
Poprzednia część tej serii wyraźnie rzuca światło na dwa inne tryby debugowania skryptów powłoki: tryb szczegółowy i tryb sprawdzanie składni z łatwymi do zrozumienia przykładami włączania powłoki debugowanie skryptów w tych trybach.
- Jak włączyć tryb debugowania skryptu powłoki w systemie Linux — część 1
- Jak wykonać tryb debugowania sprawdzania składni w skryptach powłoki – część 2
Śledzenie powłoki oznacza po prostu śledzenie wykonywania poleceń w skrypcie powłoki. Aby włączyć śledzenie powłoki, użyj opcji debugowania -x
.
To nakazuje powłoce wyświetlanie wszystkich poleceń i ich argumentów na terminalu podczas ich wykonywania.
Poniżej użyjemy skryptu powłoki sys_info.sh
, który w skrócie wypisuje datę i godzinę systemu, liczbę zalogowanych użytkowników oraz czas pracy systemu. Zawiera jednak błędy składniowe, które musimy znaleźć i poprawić.
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME
}
check_root
print_sys_info
exit 0
Zapisz plik i spraw, aby skrypt był wykonywalny. Skrypt może zostać uruchomiony tylko przez roota, dlatego użyj polecenia sudo, aby go uruchomić, jak poniżej:
chmod +x sys_info.sh
sudo bash -x sys_info.sh
Z powyższych danych wyjściowych możemy zauważyć, że polecenie jest najpierw wykonywane, zanim jego dane wyjściowe zostaną zastąpione wartością zmiennej.
Na przykład najpierw wykonano data, a jej wynik został zastąpiony wartością zmiennej DATE.
Możemy sprawdzić składnię, aby wyświetlić tylko błędy składniowe w następujący sposób:
sudo bash -n sys_info.sh
Jeśli spojrzymy krytycznie na skrypt powłoki, zdamy sobie sprawę, że w instrukcji if
brakuje zamykającego słowa fi
. Dlatego dodajmy go i nowy skrypt powinien teraz wyglądać jak poniżej:
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME
}
check_root
print_sys_info
exit 0
Zapisz plik ponownie, wywołaj go jako root i sprawdź składnię:
sudo bash -n sys_info.sh
Wynik naszej powyższej operacji sprawdzania składni nadal pokazuje, że w naszym skrypcie jest jeszcze jeden błąd w wierszy 21. Zatem nadal mamy do zrobienia pewne poprawki składniowe.
Jeśli jeszcze raz przejrzymy skrypt analitycznie, błąd w lini 21 wynika z braku podwójnego cudzysłowu zamykającego ( ”)
w ostatnim poleceniu echo wewnątrz print_sys_info
.
Do polecenia echo dodamy zamykający podwójny cudzysłów i zapiszemy plik. Zmieniony skrypt znajduje się poniżej:
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME"
}
check_root
print_sys_info
exit 0
Teraz jeszcze raz sprawdź składnię skryptu.
sudo bash -n sys_info.sh
Powyższe polecenie nie wygeneruje żadnych wyników, ponieważ nasz skrypt jest teraz poprawny składniowo. Równie dobrze możemy prześledzić wykonanie skryptu po raz drugi i powinno działać dobrze:
sudo bash -x sys_info.sh
Teraz uruchom skrypt.
sudo ./sys_info.sh
Znaczenie śledzenia wykonywania skryptów powłoki
Śledzenie skryptów powłoki pomaga nam identyfikować błędy składniowe i, co ważniejsze, błędy logiczne. Weźmy na przykład funkcję check_root
w skrypcie powłoki sys_info.sh
, która ma na celu określenie, czy użytkownik jest rootem, czy nie, ponieważ skrypt może zostać wykonany tylko przez superużytkownika.
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
Magią tutaj steruje instrukcja if
wyrażenie [ "$UID" -ne "$ROOT_ID" ]
, gdy nie użyjemy odpowiedniego operatora numerycznego ( -ne
w tym przypadku, co oznacza nie równy), może wystąpić błąd logiczny.
Zakładając, że użyliśmy -eq
(oznacza równy), pozwoliłoby to każdemu użytkownikowi systemu, a także użytkownikowi root na uruchomienie skryptu, stąd błąd logiczny.
check_root(){
if [ "$UID" -eq "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
Uwaga: jak już widzieliśmy na początku tej serii, wbudowane polecenie set Shell może aktywować debugowanie w określonej sekcji skryptu powłoki.
Dlatego poniższa linia pomoże nam znaleźć ten błąd logiczny w funkcji, śledząc jej wykonanie:
Skrypt z błędem logicznym:
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -eq "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME"
}
#turning on and off debugging of check_root function
set -x ; check_root; set +x ;
print_sys_info
exit 0
Zapisz plik i wywołaj skrypt. Widzimy, że zwykły użytkownik systemu może uruchomić skrypt bez sudo, jak pokazano poniżej. Dzieje się tak, ponieważ wartość USER_ID wynosi 100, co nie jest równe pierwiastkowi ROOT_ID, który wynosi 0.
./sys_info.sh
Cóż, na razie tyle, dotarliśmy do końca serii debugowania skryptów powłoki. Poniższy formularz odpowiedzi może służyć do kierowania do nas wszelkich pytań lub opinii dotyczących tego przewodnika lub całej 3-częściowej serii.