Shell script için zaman aşımı nasıl yapılır?


35

İçinde bir döngü olan bir kabuk betiği çalıştırmak istiyorum ve olmasını istemediğim için gidebilir. Bu yüzden tüm senaryo için bir zaman aşımı belirtmeliyim.

SuSE altında tüm kabuk betiği için zaman aşımını nasıl başlatabilirim?


4
Bu çok belirsiz bir soru. Ne tür bir zaman aşımı hakkında ayrıntılı bilgi verir misiniz? Komut dosyasının tamamında bir zaman aşımı mı yoksa tek bir işlev veya komutta zaman aşımı mı istiyorsunuz? Ne yapmaya çalışıyorsun?
Tim Kennedy

@TimKennedy: Umarım şimdi daha iyi olur.
Radek

1
Ayrıca bkz. Kabuk komut dosyasında zaman aşımına uğradı ( timeoutveya gibi araçları dışlayan taşınabilirlik gereksinimim nedeniyle yinelenen biri olarak düşünmüyorum expect)
Gilles 'ÇOK kötü olma'

Yanıtlar:


30

GNU timeoutmevcut değilse, kullanabilirsiniz expect(Mac OS X, BSD, ... genellikle varsayılan olarak GNU araçlarına ve yardımcı programlarına sahip değildir).

################################################################################
# Executes command with a timeout
# Params:
#   $1 timeout in seconds
#   $2 command
# Returns 1 if timed out 0 otherwise
timeout() {

    time=$1

    # start the command in a subshell to avoid problem with pipes
    # (spawn accepts one command)
    command="/bin/sh -c \"$2\""

    expect -c "set echo \"-noecho\"; set timeout $time; spawn -noecho $command; expect timeout { exit 1 } eof { exit 0 }"    

    if [ $? = 1 ] ; then
        echo "Timeout after ${time} seconds"
    fi

}

Örneği Düzenle :

timeout 10 "ls ${HOME}"

İyi görünüyor. Ekranda yürütülen komutun çıktısını nasıl görebilirim?
Radek

Merhaba, stdout hiçbir yere yönlendirilmediği için çıktı görünür olmalıdır. Kullanım için bir örnek ekledim. Benim durumumda, ev direktörümün içeriğini beklendiği gibi yazdırıyor. Hangi komut herhangi bir çıktı yazdırmıyor?
Matteo,

Düzgün demedim. Harika çalışıyor! Teşekkür ederim. Sadece zaman aşımından sonra saniye sayısını göstermez.
Radek

@Radek Üzgünüz, düzeltildi
Matteo

1
GNU zaman aşımı kullanılırsa, zaman aşımı durumunda timeoutkendisinin geri dönüş durumunun 124 olduğunu, aksi halde komutun geri dönüş durumunun (Tim Kennedy'nin cevabında bahsedildiğini) vurgulamak isterim .
QuasarDonkey

15

Açıklama için teşekkür ederim.

Neyin peşinde olduğunuzu gerçekleştirmenin en kolay yolu, komut dosyanızı timeoutGNU Coreutils paketindeki komut gibi bir sarmalayıcı içindeki döngüde çalıştırmaktır .

root@coraid-sp:~# timeout --help            
Usage: timeout [OPTION] DURATION COMMAND [ARG]...
   or: timeout [OPTION]
Start COMMAND, and kill it if still running after DURATION.

Mandatory arguments to long options are mandatory for short options too.
  -k, --kill-after=DURATION
                   also send a KILL signal if COMMAND is still running
                   this long after the initial signal was sent.
  -s, --signal=SIGNAL
                   specify the signal to be sent on timeout.
                   SIGNAL may be a name like 'HUP' or a number.
                   See `kill -l` for a list of signals
      --help     display this help and exit
      --version  output version information and exit

DURATION is an integer with an optional suffix:
`s' for seconds(the default), `m' for minutes, `h' for hours or `d' for days.

If the command times out, then exit with status 124.  Otherwise, exit
with the status of COMMAND.  If no signal is specified, send the TERM
signal upon timeout.  The TERM signal kills any process that does not
block or catch that signal.  For other processes, it may be necessary to
use the KILL (9) signal, since this signal cannot be caught.

Report timeout bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'timeout invocation'

Sonunda, kabukları yerleşik olmayan eğilimde, kendi zaman aşımı işlevinizi yazmaktan çok daha kolay olacaktır.


Bunu kurduğumu hemen anlamadım, çünkü gtimeoutkurulumumda (OSX) deniyordu .
Joshua Goldberg

7

Çok uzun sürerse ebeveyni öldürmek için betiğinizden bir bekçi uygulaması başlatın. Örnek:

# watchdog process
mainpid=$$
(sleep 5; kill $mainpid) &
watchdogpid=$!

# rest of script
while :
do
   ...stuff...
done
kill $watchdogpid

Bu script beş saniye sonra bekçi tarafından sonlandırılacak.


6
Ancak her zaman zaman aşımını beklemeniz gerekecek. Örneğinizde, betik çok kısa olsa bile betiğiniz her zaman 5 saniye çalışacaktır. Ayrıca bekçi köpeğinin kimliğini de saklamalı ve sonunda öldürmelisin.
Matteo,

@Matteo Fuarı yeterince. Katma.
Kyle Jones

1
Yaptığı şeyin ne olduğuna bağlı olarak, bundan daha karmaşık olabileceğini unutmayın. Bkz. Kabuk yazısında zaman aşımına
uğradı

ayrıca okuyun: PID'ler ne kadar süreyle benzersiz olarak kabul edilebilir? stackoverflow.com/questions/11323410/linux-pid-recycling
Florian Castellane

3

Orada da cratimeoutMartin Cracauer tarafından.

# cf. http://www.cons.org/cracauer/software.html
# usage: cratimeout timeout_in_msec cmd args
cratimeout 5000 sleep 600
cratimeout 5000 tail -f /dev/null
cratimeout 5000 sh -c 'while sleep 1; do date; done'

2
#!/bin/sh

# Execute a command with a timeout

if [ "$#" -lt "2" ]; then
echo "Usage:   `basename $0` timeout_in_seconds command" >&2
echo "Example: `basename $0` 2 sleep 3 || echo timeout" >&2
exit 1
fi

cleanup()
{
trap - ALRM               #reset handler to default
kill -ALRM $a 2>/dev/null #stop timer subshell if running
kill $! 2>/dev/null &&    #kill last job
  exit 124                #exit with 124 if it was running
}

watchit()
{
trap "cleanup" ALRM
sleep $1& wait
kill -ALRM $$
}

watchit $1& a=$!         #start the timeout
shift                    #first param was timeout for sleep
trap "cleanup" ALRM INT  #cleanup after timeout
"$@"& wait $!; RET=$?    #start the job wait for it and save its return value
kill -ALRM $a            #send ALRM signal to watchit
wait $a                  #wait for watchit to finish cleanup
exit $RET                #return the value

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.