GNU zaman aşımı için POSIX eşdeğeri?


14

GNU coreutils timeoutkomutu, belirli komut dosyası oluşturma durumları için son derece kullanışlıdır ve çalıştırmanın hızlı olması durumunda bir komutun çıkışının kullanılmasına izin verir ve çok uzun sürerse atlar.

timeoutYalnızca POSIX tarafından belirtilen yardımcı programları kullanmanın temel davranışına nasıl yaklaşabilirim ?


(Ben bir kombinasyonunu içerebilir düşünüyorum wait, sleep, killve başka ne ama belki daha kolay bir yaklaşım eksik bilen.)


3
Bkz . Bir kabuk komut dosyasında zaman aşımı var , ancak POSIX öncesi sistemlere taşınabilirlik istediğim için bunu bir kopya olarak görmüyorum ve arka plan işlemlerini içeren bazı çözümlerin dışladığı stdin ve stdout'u koruma gereksinimim vardı.
Gilles 'SO- kötü olmayı bırak'

command & pid=$! ; sleep 5 && kill $pid
Pandya

1
@Pandya, hafif bir yarış durumu getirmiyor, burada commandhızlı bir şekilde bitirirse pid, killkomut çalışmadan önce başka bir işlemle yeniden kullanılma şansı düşük mü? Bunu üretim kodunda istemem ....
Wildcard

Çözmeye çalıştığınız temel sorun hakkında daha fazla bilgi verebilir misiniz? Neden sadece timeoutprogramı derleyip kullanmıyorsunuz?
James Youngman

2
@JamesYoungman, taşınabilirlik için komut dosyaları yazmaya çok aşina olmadığınızı tahmin ediyorum . POSIX uyumlu (veya POSIX tarafından belirtilen) bir şey yapmanın istenmesi, taşınabilir olması gerektiği anlamına gelir . Bir ikili içine Kaynak kodunun derlenmesi kesinlikle taşınabilir değildir ve, şirket güvenlik politikasına bağlı olarak yüklü bir derleyici olmayabilir hiç bir üretim sunucusuna.
Wildcard

Yanıtlar:


2

Benim yaklaşımım şu olurdu:

  • Arka plan işlemi olarak komut yürütmek 1

  • Arka plan işlemi 2 olarak "bekçi köpeği zamanlayıcı" yürütmek

  • Üst kabukta bir sonlandırma sinyali yakalamak için bir işleyici ayarlayın

  • Her iki işlemin de tamamlanmasını bekleyin. İlk önce sonlanan işlem, sonlandırma sinyalini ebeveyne gönderir.

  • Ebeveynin tuzak işleyicisi her iki arka plan sürecini iş kontrolü yoluyla öldürür (bunlardan biri tanım gereği zaten sonlandırılmıştır, ancak bu öldürme zararsız bir işlem olmayacaktır, çünkü PID kullanmıyoruz, aşağıya bakın)

Sistem PID'leri yerine öldürülecek arka plan işlemlerini tanımlamak için kabuğun iş denetim kimliklerini (bu kabuk örneği içinde açık olacaktır) kullanarak yorumlarda ele alınan olası yarış durumunu atlatmaya çalıştım.

#!/bin/sh

TIMEOUT=$1
COMMAND='sleep 5'

function cleanup {
    echo "SIGTERM trap"
    kill %1 %2
}

trap cleanup SIGTERM

($COMMAND; echo "Command completed"; kill $$) &
(sleep $TIMEOUT; echo "Timeout expired"; kill $$) &

wait
echo "End of execution"

Sonuç TIMEOUT=10(komut beklemeden önce sonlandırılır):

$ ./timeout.sh 10
Command completed
SIGTERM trap
End of execution

Sonuç TIMEOUT=1(watchdog komuttan önce sona erer):

$ ./timeout.sh 1
Timeout expired
SIGTERM trap
End of execution

Sonuç TIMEOUT=5(bekçi köpeği ve komut aynı anda "neredeyse" sona erdirir):

./tst.sh 5
Timeout expired
Command completed
SIGTERM trap
End of execution

Bu, (a) işlev tanımının olması gerektiği cleanup() { ...; }ve (b) iş kontrolü POSIX tarafından belirtilmeyen bir bash özelliğidir (ksh ve diğerlerinin de sahip olması) nedeniyle POSIX ile uyumlu değildir. Güzel senaryo olsa!
Wildcard

Ayrıca daha iyi yapabileceğini timeout="$1"; shiftve (exec "$@"; echo "Command completed"; kill $$)argüman listesi yeniden wordsplitting yerine.
Wildcard
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.