Witam
Chciałbym napisać skrypt który będzie pingował jakiś określony host w sieci, i gdy ping-u nie będzie wykona inny skrypt oraz zrobi zapis do zmiennej.
Rozpisałem sobie mniej więcej założenia które chciałbym aby skrypt spełnił i wygląda to tak
1. Monitorowanie adresu IP
2. Przypadku braku odpowiedzi na ping :
2a - Wysyła sms/email
2b - Uruchamia inny skrypt który zmienia trasę
2c - Robi wpis np do jakiegoś pliku lub zmiennej, że nie działa
3. W przypadku braku odpowiedzi na ping, i zmiennej że nie działa nie robi nic
4. W przypadku powrotu pingu, ale zmiennej że nie działa nie robi nic
5. Skrypt opiera się na w/w zmiennej i podejmuje działanie(zmianę trasy poprzez wykonanie innego skryptu) tylko wtedy, gdy zmienna jest np działa
Inny skrypt podczas zmiany trasy z zapasowej na domyślą będzie miał robić zmianę tej zmiennej z nie działa na działa
Od czego powinienem zacząć?
Pozdrawiam
Napisz jakikolwiek skrypt, bo na razie nie wiadomo w czym masz problem.
Dodatkowo większość odpowiedzi masz w internecie. " linux pytanie "
Kwestia czasu by znaleźć.
Np.
#!/bin/bash
IP="192.168.0.77"
LOSS=$(ping -c 1 "$IP" | grep -oP '\d+(?=% packet loss)')
if [[ "$LOSS" == "0" ]]; then
echo "${LOSS}"
echo "IP odpowiedzial"
elif [[ "$LOSS" == "" ]] ; then
echo "Bledny adres IP"
else
echo "$LOSS"
echo "Nie przyszla odpowiedz od $IP"
logger -p news.alert "Nie przyszla odpowiedz od $IP"
echo "Sprawdzamy syslog:"
grep "Nie przyszla odpowiedz od $IP" /var/log/syslog
echo "Sprawdzamy journalctl:"
journalctl -b0 | grep "Nie przyszla odpowiedz od $IP"
fi
" zapis do zmiennej "
--> linux bash zapis do zmiennej
https://duckduckgo.com/?q=linux+bash+zapis+do+zmiennej&t=lm&ia=web
Czyli znajdziesz to w kursach bash
--> linux bash save to variable
https://duckduckgo.com/?q=linux+bash+save+to+variable&t=lm&ia=web
Znajdziesz to także w odpowiedziach np. na stackoverflow.com , unix.stackexchange.com
i na blogach w postaci poradników czy kursów bash
Czy zapisać wynik czyli "output" do zmiennej czy do pliku to zależy tylko od twojej wygody.
Ja bym nie zaśmiecał komputera zbędnymi plikami jeśli to możliwe.
W powyższym przykładzie LOSS to zmienna przechowująca wynik komendy ping.
Powyższa komenda ping
ping -c 1 "$IP" | grep -oP '\d+(?=% packet loss)'
powinna dać wynik 0 lub 100 lub nic. Uwzględnione to jest w warunku " if ".
Podałem także przykład z komendą "logger" jak zapisać komunikat do logu systemowego.
Oraz jak można znaleźć komunikat w logach syslog i journalctl.
Wiecej o komendach przeczytasz wpisując w terminalu
Do pomocy możesz także używać
https://explainshell.com/
shellcheck które można zainstalować i używać do sprawdzania pisowni lub niektórych błędów w skryptach. Należy traktować raczej jako podpowiedz niż wymóg.
Jeszcze coś
Użycie komendy grep do wyciągnięcia określonego fragmentu tekstu czasami jest nazywane parsowaniem.
Polecane jest używanie języka bash https://www.thegeekstuff.com/2010/07/bash-string-manipulation/
Np. użycie pętli while i jeśli wartość się zgadza to wypisanie wartości / tekstu i wyjście z pętli.
Ja osobiście lubię korzystać z komend nie wbudowanych w bash typu: sed , awk .
Komenda compgen może pokazać listę wbudowanych komend https://unix.stackexchange.com/questions/151118/understand-compgen-builtin-command
Czy zapisać wynik czyli "output" do zmiennej czy do pliku to zależy tylko od twojej wygody.
Ja bym nie zaśmiecał komputera zbędnymi plikami jeśli to możliwe.
W moim przypadku lepiej chyba do pliku, bo inny skrypt będzie zmieniał tą zmienną jeśli przełączy na trasę domyślną
Zrobiłem coś takiego
#!/bin/bash
IP="10.18.18.1"
LOSS=$(ping -c 1 "$IP" | grep -oP '\d+(?=% packet loss)')
STAN=$(cat stan |grep Dziala)
if [[ "$STAN" == "Dziala" ]]; then
if [[ "$LOSS" == "0" ]]; then
echo "Trasa domyslna odpowiada"
echo "Dziala" > stan
elif [[ "$LOSS" == "" ]] ; then
echo "Bledny adres IP"
else
echo "Host nie odpowiada"
echo "Wysyłam SMS"
#Skrypt do SMS
echo "Wysyłam email"
#Skrypt do email
echo "Uruchamiam skrypt do zmiany trasy"
#Skrypt do zmiany trasy
echo "Zmieniam stan trasy"
echo "Nie dziala" > stan
fi
else
echo "Zmien trase ręcznie"
fi
Jednak niezależnie od tego czy ping jest czy nie ma zwraca mi wynik
Nie bardzo wiem teraz co jest źle :/
if [[ "$STAN" == "Dziala" ]]; then
...
else
echo "Zmien trase ręcznie"
fi
Czyli zmienna STAN ma inną wartość niż " Dziala "
Jaką wartość ma zmienna STAN i dlaczego ?
STAN=$(cat stan | grep Dziala)
Komenda grep wyświetla linię zawierającą tekst Dziala z pliku stan.
1. Może to być kilka linii.
2. Te linie mogą zawierać inny tekst lub spacje.
3. Plik może być pusty, więc zmienna także może być pusta.
A to nie będzie równe słowu " Dziala " i w konsekwencji otrzymasz komunikat " Zmien trase ręcznie "
Proces szukania błędu nazywane jest często debugowaniem.
Możesz poszukać i poczytać https://duckduckgo.com/?t=lm&q=linux+bash+debug&ia=web
Generalnie chodzi o używanie technik ułatwiających znalezienie błędu, np.
1. Wyświetlenie zmiennej z którą mamy problem.
np. ja wyżej użyłem echo "$LOSS" do wyświetlenia zmiennej LOSS by zobaczyć co ona zawiera.
Spacji nie zobaczysz, ale możesz je zamienić lub dopisać widoczny znak do zmiennej by zobaczyć czy te spacje są. np.
$ DRZEWO="sosna" ; DRZEWO_DEBUG="A${DRZEWO}A" ; echo "$DRZEWO_DEBUG"
AsosnaA
Jak widzisz zmienna DRZEWO nie zawiera spacji, bo nie widać ich pomiędzy literami " A ".
Po drugie takie sprawdzanie w terminalu na przykładach to też fajny sposób debugowania.
2. Uruchomienie skryptu z opcją -x aby zobaczyć co robi.
Dziękuję za pomoc i wyczerpującą odpowiedz,
zmieniłem te zmienne na bez spacji, i trochę przerobiłem if-y
#!/bin/bash
IP="10.18.18.1"
LOSS=$(ping -c 1 "$IP" | grep -oP '\d+(?=% packet loss)')
STAN=$(cat stan)
if [[ "$LOSS" == "0" ]]; then
echo "Trasa domyslna odpowiada"
echo "trasa_on" > stan
elif [[ "$LOSS" == "" ]] ; then
echo "Bledny adres IP"
else
echo "Host nie odpowiada"
echo "trasa_off" > stan
fi
if [[ "$STAN" == "trasa_off" ]]; then
echo "Uruchamiam drugi skrypt"
elif [[ "$STAN" == "" ]] ; then
echo "Nieznany stan"
else
echo "dziala"
fi
Plik stan zawiera tylko "trasa_on" lub "trasa_off"
I ogólnie działa mniej więcej tak jak powinno, tylko problem jest taki, że skrypt musi zostać uruchomiany drugi raz aby zaczytał zmianę zmiennej.
Wydaje mi się, że skrypt w bash tak jakby zatrzymuję czas w chwili uruchomienia skryptu, i nie bierze pod uwagę zmiany pliku stan.
Dobrze myślę? Jest na to jakiś sposób aby to zrobić w jednym skrypcie czy musiałbym to rozbić jakoś na dwa?
Zrozumiałem Cię tak.
#!/bin/bash
IP="192.168.0.77"
STAN=$(cat stan)
LOSS=$(ping -c 1 "$IP" | grep -oP '\d+(?=% packet loss)')
# Jeśli w pliku "stan" jest zapis "trasa_on",
if [[ "$STAN" == "trasa_on" ]]; then
# a ping do hosta jest to ping odpowiada i skrypt się kończy.
if [[ "$LOSS" == "0" ]]; then
echo "Trasa domyslna odpowiada"
echo "Koniec skryptu"
exit 0
elif [[ "$LOSS" == "" ]] ; then
echo "Bledny adres IP"
else
echo "Host nie odpowiada"
# ping do hosta przestaje odpowiadać
# to skrypt zmienia zapis w pliku "stan" na "trasa_off"
echo "trasa_off" > stan
# i będzie uruchamiał zewnętrzny skrypt który zmieni mi trasę ruchu.
echo "Uruchamiam drugi skrypt"
fi
elif [[ "$STAN" == "trasa_off" ]]; then
if [[ "$LOSS" == "0" ]]; then
echo "Trasa domyslna odpowiada"
# ping odpowiada, ale zapis w pliku "stan" jest "trasa_off".
# Wtedy skrypt nie robi nic, tylko kończy.
echo "Koniec skryptu"
exit 0
elif [[ "$LOSS" == "" ]] ; then
echo "Bledny adres IP"
else
echo "Host nie odpowiada"
fi
else
echo "Bledna / inna zawartosc pliku stan."
fi
i jest to trochę inaczej niż napisałeś w skrypcie.