in attesa di rete in uno script bash


9

Sto eseguendo uno script che si basa sul fatto che la rete sia attiva e che venga montata una condivisione di rete. Lo script viene eseguito all'accesso (che si verifica automaticamente dopo l'avvio). Il problema è che quando lo script viene eseguito, di solito non ho ancora un indirizzo IP (DHCP). Al momento dormo solo lo script per 15 secondi, ma non mi piace affatto questo approccio, dal momento che voglio essere in grado di dire all'utente se qualcosa non va.

Qual è il mio piano, è un ciclo mentre non ho ancora un indirizzo IP e continuare quando lo faccio. Fondamentalmente, deve scadere dopo un po '. Quello che mi è venuto in mente è di farlo, if [ ifconfig | grep "192.168.100" ];ma ciò che accade è che ];non lo utilizza. Quindi anche bash si arrabbia, perché non riesce a trovare ];quale grep ha mangiato. E poi non ho nemmeno implementato il timeout.

Qualcuno ha suggerito di mantenere una variabile e dormire per, diciamo, un secondo in ogni iterazione e aumentare questa variabile ogni volta. Ecco il mio script completo (non funzionante) (sono abbastanza nuovo per lo script bash):

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
    echo "no nework"
    if "$x" -gt 200; then
        #Time out here
        exit 1
    x=$((x+1))
    sleep .1
    fi
done

#continue with rest of script...

Eventuali puntatori nella giusta direzione sarebbero molto apprezzati!


1
Se il tuo init è systemd, scrivi un file di servizio che attende network-online.target...
jasonwryan,

non è necessario reindirizzare l' grepoutput a /dev/null. Usa -qinvece l'opzione. E anche io non ho niente a che vedere con ifconfig è una buona idea. Perché non usare pinginvece?
precipita il

pingpuò fallire a seconda della rete in questione. È meglio controllare solo la configurazione in esecuzione del sistema.
Bratchley,

Risposte:


8

Sintassi della shell

Sembra che tu sia confuso riguardo ai condizionali negli script di shell. Ogni comando shell ha uno stato di uscita, che è un numero intero compreso tra 0 e 255, con 0 che indica l'esito positivo e qualsiasi altro valore che indica l'errore. Dichiarazioni come ife whileche prevedono operandi booleani controllano lo stato di uscita del comando e trattano 0 (esito positivo) come vero e qualsiasi altro valore (esito negativo) come falso.

Ad esempio, il grepcomando restituisce 0 se viene trovato il modello e 1 se il modello non viene trovato. Così

while ifconfig | grep "192.168.100." > /dev/null; do 

ripete il loop fintanto che il pattern 192.168.100.si trova nell'output di ifconfig. Si noti che il modello 192.168.100.corrisponde a stringhe come 192x168 1007, perché .in un'espressione regolare corrisponde a qualsiasi carattere; per cercare una stringa letterale, passare l'opzione -Fa grep. Per invertire la condizione, mettiti !di fronte.

while ! ifconfig | grep -F "192.168.100." > /dev/null; do 

Inoltre nello script, si desidera confrontare il valore di una variabile con un numero. Si utilizza l' -gtoperatore, che fa parte della sintassi delle espressioni condizionali comprese dal testcomando. Il testcomando restituisce 0 se l'espressione condizionale è vera e 1 se l'espressione condizionale è falsa.

if test "$x" -gt 200; then

È consuetudine utilizzare il nome alternativo [per il testcomando. Questo nome prevede che il comando termini con il parametro ]. I due modi di scrivere questo comando sono esattamente equivalenti.

if [ "$x" -gt 200 ]; then

Bash offre anche un terzo modo per scrivere questo comando, con la sintassi speciale [[ … ]]. Questa sintassi speciale può supportare alcuni operatori in più rispetto a [, poiché [è un comando ordinario soggetto alle consuete regole di analisi, mentre [[ … ]]fa parte della sintassi della shell.

Ancora una volta, tieni presente che [è per le espressioni condizionali , che sono una sintassi con operatori come -n, -gt... [non significa "valore booleano": qualsiasi comando ha un valore booleano (exit status = 0?).

Rilevamento che la rete è attiva

Il tuo modo di rilevare che la rete è attiva non è affidabile. In particolare, si noti che lo script verrà attivato non appena un'interfaccia di rete acquisisce un indirizzo IP nell'intervallo specificato. In particolare, è abbastanza probabile che DNS non sarà ancora attivo a quel punto, per non parlare di eventuali condivisioni di rete montate.

Hai davvero bisogno di eseguire questi comandi quando qualcuno accede? È più semplice eseguire automaticamente un comando all'avvio della rete. Il modo per farlo dipende dalla distribuzione e dall'utilizzo di NetworkManager.

Se è necessario eseguire questi comandi come parte degli script di accesso, quindi verificare la risorsa di cui si ha realmente bisogno, non la presenza di un indirizzo IP. Ad esempio, se si desidera verificare se /net/somenode/somedirè montato, utilizzare

while ! grep -q /net/somenode/somedir </proc/mounts; do
  sleep 1
done

Se hai avviato o systemd ...

allora puoi usarlo. Ad esempio, con Upstart , contrassegnare il lavoro come start on net-device-up eth0(sostituire eth0con il nome dell'interfaccia che fornisce la connettività di rete desiderata). Con Systemd, vedi Causa uno script da eseguire dopo l'avvio della rete?


Immagino che /net/dovrebbe essere /proc/net?
Sebix

@sebix No, perché dovrebbe? Non sto parlando della configurazione di rete di Linux. Sto dando un esempio di un mount point per un filesystem remoto, /netè una posizione comune per tali mount points.
Gilles 'SO- smetti di essere malvagio'

Ok, quindi hai bisogno di un'unità di rete montata. Esiste anche una soluzione più generica?
Sebix

@sebix Una soluzione per cosa? La richiesta di un'unità di rete montata era un esempio di obiettivo, non un esempio di soluzione.
Gilles 'SO- smetti di essere malvagio'

1

Basta contare l'output di ip add showAd esempio:

root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
    inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
    inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2

Quindi puoi semplicemente ramificare il numero di riga restituito come appropriato. Probabilmente verifichi semplicemente se era zero e, in tal caso, dormi e ripeti il ​​ciclo.

Codice non testato per l'illustrazione:

while [ 1 ]; do

  if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
     break
  fi

  sleep 1

done

1

Il ping restituirà una risposta 0 se almeno un tentativo ha avuto esito positivo. È possibile eseguire il ping del server a cui ci si sta connettendo fino a quando non ha esito positivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.