Bir sunucuyu uzaktan test etmeye devam eden bir kabuk komut dosyası yazmaya çalışıyorum, ancak çıkış yaptığımda başka bir ifadede düşmeye devam ediyor


9

Sunucumu test etmeye devam eden bir kabuk komut dosyası yazmaya ve çalıştığında bana e-posta göndermeye çalışıyorum.

Sorun şu ki, ssh bağlantısından çıkış yaptığımda &, komutun sonunda çalıştırılmasına rağmen ./stest01.sh &, otomatik olarak başka bir şeye düşüyor ve tekrar giriş yapıp öldürene kadar sürekli olarak postalamaya devam ediyor.

#!/bin/bash
while true; do
    date > sdown.txt ;
    cp /dev/null pingop.txt ;
    ping -i 1 -c 1 -W 1 myserver.net > pingop.txt &
    sleep 1 ;
    if
        grep "64 bytes" pingop.txt ;
    then
        :
    else
        mutt -s "Server Down!" myemail@address.com < sdown.txt ;
        sleep 10 ;
    fi
done

1
Ben bash uzmanı değilim, ama kolon ne yapıyor :? Noktalı virgül olması bana mantıklı ;...
Ned64

3
@ Ned64 :Hiçbir şey yapmaz. Bunu yapmak için tasarlandı. Burada, testi tersine çevirmek yerine, daha önce işlem yapmamak için kullanıyorlar else.
Kusalananda

@Kusalananda Tamam, teşekkürler. Sorunu açıklayabilecek bir yazım hatası olabileceğini düşündüm.
Ned64

1
Ayrıca neden bir çıkış sonra çalışan bir kabuk komut dosyası bırakmaya çalışacağım karıştı. Bunun için cron veya systemd zamanlayıcıları daha iyi bir seçim olmaz mı?
Cliff Armstrong

Yanıtlar:


20

GNU grepsonucunu yazmaya çalıştığında, sıfır olmayan bir çıkış durumuyla başarısız olur, çünkü SSH bağlantısı gittiği için çıktı yazacak hiçbir yeri yoktur.

Bu, ififadenin her zaman elsedalı ele aldığı anlamına gelir .

Bunu göstermek için (bu tam olarak sizin durumunuzda olan şey değildir , ancak GNU grepçıktısını yazamazsa ne olacağını gösterir ):

$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2

Burada üreten grepdize echoiçiniz, ancak her iki çıktı akışını grepda hiçbir yere yazamamak için kapatıyoruz . Gördüğünüz gibi, GNU'nun çıkış durumu grep0 yerine 2'dir.

Bu GNU özgü olan grep, grepaynı uslu durmuyor BSD sistemlerde:

$ echo 'hello' | grep hello >&- 2>&-    # using BSD grep here
$ echo $?
0

Bunu düzeltmek için komut dosyasının çıktı oluşturmadığından emin olun. Bunu ile yapabilirsiniz exec >/dev/null 2>&1. Ayrıca, ondan çıktıyı görmekle hiç ilgilenmediğimiz grepiçin -qseçeneğiyle birlikte kullanmalıyız (bu genellikle tüm dosyayı ayrıştırması gerekmediği için hızlanır , ancak bu durumda çok az dosyadaki çok küçük olduğundan hızdaki fark).grep

Kısacası:

#!/bin/sh

# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1

while true; do
    date >sdown.txt

    ping -c 1 -W 1 myserver.net >pingop.txt

    if ! grep -q "64 bytes" pingop.txt; then
        mutt -s "Server Down!" myemail@address.com <sdown.txt
        break
    fi

    sleep 10
done

Ayrıca ping, ara dosyalardan birine olan ihtiyacı ortadan kaldırarak (ve gerçekten yalnızca bir tarih damgası içeren diğer ara dosyadan kurtularak) doğrudan bir test de kullanabilirsiniz :

#!/bin/sh

exec >/dev/null 2>&1

while true; do
    if ! ping -q -c 1 -W 1 myserver.net; then
        date | mutt -s "Server Down!" myemail@address.com
        break
    fi

    sleep 10
done

Yukarıdaki komut dosyasının her iki varyasyonunda, yalnızca gönderilen e-posta sayısını en aza indirmek için ana bilgisayara ulaşılamadığında döngüden çıkmayı seçiyorum. Sunucunun sonunda tekrar ortaya çıkmasını bekliyorsanız bunun yerine breakörneğin sleep 10mveya başka bir şeyle değiştirebilirsiniz .

Ben de pek mantıklı değil pinggibi kullanılan seçenekleri biraz tweaked .-i 1-c 1

Daha kısa (ana bilgisayara erişilemediğinde e-posta göndermeye devam etmesini istemiyorsanız):

#!/bin/sh

exec >/dev/null 2>&1

while ping -q -c 1 -W 1 myserver.net; do
    sleep 10
done

date | mutt -s "Server Down!" myemail@address.com

Her dakika çalışan bir cron işi olarak (sunucu kapanmaya devam ederse her dakika e-posta göndermeye devam eder):

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )

Kullanmak >&-fd kapatır (olduğu gibi, dosya tanımlayıcı 1 kapalı), SSH bağlantısı kapatılırken farklı bir etkisi olacaktır (bir dosya tanımlayıcı hala etrafında olacak, ancak diğer taraftaki hiçbir şeye bağlı değil.) Bence nokta hala duruyor, yani çıktı yazmaya çalışırsa GNU grep sıfırdan çıkar ve bu başarısız olur. Evet, en iyi çözüm sadece doğrudan ping çıkış durumunu kontrol etmektir.
filbranden

4
Her şeyi exec </dev/null >/dev/null 2>&1başlangıca yakın ekleyerek tüm komut dosyası için / dev / null dizinine yönlendirmek daha güvenli olabilir . Bu şekilde, örneğin pingstderr'a bir şeyler yazmaya karar verirse, bu bir soruna neden olmaz.
Gordon Davisson

@GordonDavisson Stdin'i /dev/nullburadan çekmek için gerçekten bir neden göremiyorum , ancak çıktıyı çözdüm . Önerin için teşekkürler.
Kusalananda
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.