Skript pro hlídání odpojení od sítě

script-iconV práci celkem často pracuji buďto z domu nebo jinde na cestách skrze jiné sítě, ať již domácí wifi nebo GPRS/EDGE/3G,… whatever. Všechny tyto připojení mají jedno společné — nejsem v pracovní síti a jsem nucen použít VPN konektivitu. Bohužel se mi čas od času stane, že mi VPN pouze vytuhne, ale nevypadne. Problém se projeví tak, že sice jsem dle ikonek a dle statusu připojen, ale na firemní servery se nedostanu. Bohužel se toto projevuje vždy v ten nejméně vhodný okamžik. Doteď jsem to řešil tak, že jsem hlídal ping na jeden náš interní server. Pokud ping chodil, bylo vše OK. Pokud se zastavil, bylo jasné, že mi vypadla VPN. Nyní jsem se rozhodl, že takto mě to nebaví a napsal si pro to krátký skriptík. (Updated: new bugfix)

Co skript má dělat již zhruba chápete. Nechce se mi rozepisovat „jak“. Ti, co to vidí, to vidí. Ti, co nikoli, těm asi rozbor stejně nepomůže (ale rád vysvětlím, jen nechci ztrácet čas něčím, co stejně nikdo neocení). Stále využívá příkazu ping. Pošle pár packetů a pokud se nevrátí do určitého časového intervalu, je to považováno za problém na síti a skript pošle přes notifikačního démona upozornění… Pak skript začal bobtnat… Tentokrát to ale udělám jinak. Napíšu, jak skript použít, nebudu se moc rozepisovat o tom, jak to funguje.

Začněme zvolna funkcí nápovědy.

  1. [safarikp@Lacerta ~]$ vpnCheck -h
  2. Usage: vpnCheck [OPTIONS]
  3. Options are:
  4. -d destination -- server to watch [localhost]
  5. -w wait -- timeout for ping in s [5]
  6. -c count -- count of ping packets to fail [3]
  7. -s sleep -- interval between 2 ping commands in s [15]
  8. -l -- list all monitors
  9.  
  10. By Petos (http://petos.cz), under GPLv2+

Skript je možné spustit tak, aby hlídal libovolné množství serverů ovšem pouze jedna instance monitoru může být spuštěna vůči jednomu serveru (tj. můžete monitorovat google.com, gmail.com a petos.cz, ale na každý jeden monitorovaný server můžete mít spuštěn pouze jednu instanci skriptu. Toto je zajištěno systémem „zámků“ v /tmp.

Co to vlastně dělá?

Věřím sice, že jsem základ již vysvětlil. Skript hlídá, je-li nějaký server „dopingatelný“ a v případě, že není, informuje uživatele.

Jak to spustit?

Skript stáhněte a uložte někam, kam povede $PATH a přidejte mu právo ke spuštění. Otevřete si skript pro editaci a upravte řádky s výchozími hodnotami (vizte pár bodů níže). Hlavně upravte řádek DEST="localhost" na váš výchozí server!!!

Jak to stáhnout

Klikni na STÁHNOUT.

Co všechno je tedy možné nastavit:

Přímo v kódu jsou na několika řádcích definovány výchozí parametry, nebo je možné parametry upravit při spuštění.

  • Server, vůči kterému kontrolujeme, že jsme „v síti“ (nebo naopak jehož přítomnost v síti kontrolujeme). Výchozí hodnota je „localhost„. Parametr -d či DEST.
  • Časový interval, do kterého se musí packet vrátit. V případě překročení je indikován problém. Výchozí hodnota je 5. Parametr -w či PNGW.
  • Počet pokusných packetů, které se posílají. Výchozí hodnota je 3. Parametr -c či PNGC.
  • Čas mezi dvěmi pingy. Výchozí hodnota 15s. Parametr -s či SLEEP.
  • ERRORICON obsahuje cestu k ikoně použité v případě chyby.
  • INFOICON obsahuje cestu k ikoně použité v případě varování, že jeden monitor již je aktivní.

Jediné, co byste opravdu měli upravit přímo ve skriptu je parametr DEST, který vede na váš vlastní počítač localhost. V případě, že se vám nezobrazují ikonky, překontrolujte si i nastavení ERRORICON a INFOICON, jestli vedou na existující soubory.

Jak vypíšu všechny spuštěné monitory?

K tomuto slouží parametr -l. V terminále spusťtě vpnCheck -l. Na výstupu uvidíte tabulku, kde v prvním sloupci je text vpnCheck.SERVER.lock a ve druhém sloupci je PID aplikace.

  1. vpnCheck -l
  2. Destination | PID
  3. bambam | 17991
  4. google.com | 17575

Jak vypnu spuštěné monitory?

Prvně si vypište všechny monitory pomocí vpnCheck -l. Vyberte ten, který chcete vypnout a najděte jeho PID (druhý sloupec tabulky). Nakonec použijte

  1. kill <PID>

kde <PID> je číslo z vpnCheck -l tabulky.

Jak to vše funguje?

Jádro aplikace je poměrně jednoduché:

  1. FAILS=0
  2. TOTFAILS=0
  3.  
  4. while true; do
  5. PINGANS=0
  6.  
  7. while [ $PINGANS = 0 ]; do
  8. ping -q -c $PNGC -w $PNGW $DEST >> /dev/null
  9. PINGANS="$?"
  10. if [ $PINGANS = 0 ]; then
  11. sleep "$SLEEP"
  12. FAILS=0
  13. fi
  14. done
  15.  
  16. ((++FAILS))
  17. ((++TOTFAILS))
  18.  
  19. if [ $FAILS = 2 ]; then
  20. echo -e "\n \n \n \n Connection to $DEST is down\n \n \n"
  21. wall "Connection to $DEST is down"
  22. notify-send --urgency=critical -i $ERRORICON --app-name="Monitor" "Connection to $DEST is down"
  23. sleep 50
  24. fi
  25. done

Skript pošle ping s přijatými (nebo výchozími) parametry pro -c a -w na referenční server a výstup zahodí. V případě, že je návratová hodnota nulová, zavolá se příkaz sleep a počká se. V případě, že návratová hodnota je ovšem dvakrát po sobě nenulová, vypíše se chybová hláška na terminály a poté pomocí notify-send na notifikačního démona. Poté se počká 60 vteřin a test se opakuje.

Zámky, k čemu to je dobré?

Pro vás? K ničemu. Pouze vás omezují, abyste neměli víc jak jeden monitor na server. Navíc jsou použity pro vypsání všech monitorů.  Podívejme se na obě funkce, které zámky využívají.

Zámek má vždy jméno vpnCheck.<SERVER>.lock, kde <SERVER> je označení použité v parametru -d (případně výchozí hodnota). Obsahem souboru se zámkem je PID tak, že je možné jednoduše jednotlivé monitory identifikovat.

  1. check_running()
  2. {
  3. if [ -e /tmp/"$SCRIPTNAME"."$DEST".lock ]; then
  4. RUNNINGPID=$(ps -ef | grep $(cat /tmp/"$SCRIPTNAME"."$DEST".lock) | grep -v grep | grep $SCRIPTNAME)
  5. if [ "$RUNNINGPID" ]; then
  6. echo "One vpnCheck for $DEST is up, please kill $(cat /tmp/"$SCRIPTNAME"."$DEST".lock)"
  7. notify-send --urgency=normal -i $INFOICON --app-name="Connection Monitor" "Connection Monitor was not started" "One vpnCheck for $2 is up, please kill $(cat /tmp/"$SCRIPTNAME"."$DEST".lock)"
  8. exit 0
  9. fi
  10. fi
  11. }

Jak jsem psal, zámky slouží k identifikaci již běžících monitorů. Tento zámek se kontroluje ve funkci check_running(). V prvním řádku se překontroluje, jestli již zámek pro daný server existuje. Pokud ano, zjistí se, zda-li proces s daným PID existuje a jestli patří vpnCheck skriptu. Pokud je obojí odpověď ano, vypíše chybové hlášení a ukončí se.

  1. function list_monitors()
  2. {
  3. echo "Destination | PID"
  4. if [ $(ls /tmp/"$SCRIPTNAME".*.lock 2> /dev/null | wc -l) != 0 ]; then
  5. for MON in /tmp/"$SCRIPTNAME".*.lock; do
  6. RUNNINGPID=$(ps -ef | grep $(cat $MON) | grep -v grep | grep $SCRIPTNAME)
  7. if [ "$RUNNINGPID" ]; then
  8. MONAPP=$(echo $MON | awk -F '/tmp/'$SCRIPTNAME. '{print $2}' | awk -F '.lock' '{print $1}')
  9. echo "$MONAPP | $(cat $MON)"
  10. fi
  11. done
  12. fi
  13. exit 0;
  14. }

Druhou funkcí je funkce list_monitors(), která slouží pro výpis běžících monitorů (volání vpnCheck -l ). Prvně vypíše hlavičku. Následně probere jednotlivé zámky (lock-soubory) a překontroluje, zda-li existuje proces s PID v zámku a jestli tento proces je právě skript. Pokud ano, tak vypíše jméno zámku a potom PID.

Update 8. ledna: Přidána podmínka do list_monitors()

  1. if [ $(ls /tmp/"$SCRIPTNAME".*.lock 2> /dev/null | wc -l) != 0 ]; then

která zajišťuje kontrolu zámků pouze v případě, že nějaké zámky opravdu existují.

1 komentář u „Skript pro hlídání odpojení od sítě“

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *