Komutu her X saniyede bir gerçekleştir


10

Ben 10 saniye boyunca bir komut gerçekleştirmek ve arka planda yürütmek istiyorum (böylece ortadan kaldırmak watch?). Tüm cevaplar aşağıdaki gibi bir şey gösterir, ancak bu 11 ila 14 saniye arasında yürütülür. Bu nasıl yapılabilir?

while true; do
    # perform command that takes between 1 and 4 seconds
    sleep 10
done

belki de gerçek zamanlı sinyallerle. ve artık saniyelerin uygun şekilde kullanılması. iyi şanslar.
mikeserv

@mikeserv Peki, denemeye zahmet etme? Milyon saniye doğruluğu umrumda değil, sadece yarım saniye söyleyin.
user1032531

Ne yapmaya çalışıyorsun? Bu tür bir sıklıkta çalışması gereken bir görevin genellikle başka bir sorun için geçici bir çözüm olduğunu görüyorum.
Sobrique

@Sobrique Aynen öyle. Yoklama veri kaydedici kavramının bir kanıtı yapıyorum. Gerçekte, başka bir dilde programlanacaktır, ancak bu şimdilik işe yarıyor.
user1032531

Yanıtlar:


16

Nasıl olur:

( # In a subshell, for isolation, protecting $!
  while true; do
    perform-command & # in the background
    sleep 10 ;
    ### If you want to wait for a perform-command
    ### that happens to run for more than ten seconds,
    ### uncomment the following line:
    # wait $! ;
    ### If you prefer to kill a perform-command
    ### that happens to run for more than ten seconds,
    ### uncomment the following line instead:
    # kill $! ;
    ### (If you prefer to ignore it, uncomment neither.)
  done
)

ETA: Tüm bu yorumlar, alternatifler ve ekstra koruma için alt kabuk ile, bu başlangıçtan çok daha karmaşık görünüyor. Yani, karşılaştırma için, endişelenmeye başlamadan önce waitya da izolasyon gereksinimlerine killsahip gibi görünüyordu $!:

while true; do perform-command & sleep 10 ; done

Gerisi gerçekten ihtiyacınız olduğunda.


Kod dökümünüzün ardındaki mantığı açıklayabilir misiniz?
Ismael Miguel

2
Ayrıca, kodunuzun hangi kabuk için çalıştığını belirtmek için (mikeserv'in cevabı gibi), böylece farklı bir kabuk farklı davrandığında insanlar karışmaz :)
ash

@IsmaelMiguel Yorumların muhakemeyi açıklayacağını düşündüm. Neyin belirsiz olduğundan emin değilim.
Sidhekin

1
Bash el kitabı şöyle diyor $!: "En son arka plana yerleştirilen işin işlem kimliğine genişler" ve sleeparka plana yerleştirilmez, bu nedenle hayır olmaz. :)
Sidhekin

1
vay. her iki konuda da yanlış. bu ne zaman oldu?
mikeserv

9

Sen şu gibi bir şey yapabilirsiniz bash, zshveya ksh:

SECONDS=0
while   command
do      sleep "$((10-(SECONDS%10)))"
done

İşte ne bashmanuel diyor $SECONDS:

$SECONDS

  • Bu parametreye her başvuruda bulunulduğunda, kabuk çağrılmasından bu yana geçen saniye sayısı. Bir değer atanırsa $SECONDS, sonraki başvurularda döndürülen değer, atamadan sonraki saniye sayısı ve atanan değerdir. Öyleyse $SECONDS, unsetdaha sonra sıfırlansa bile özel özelliklerini kaybeder.

İşte çalışan bir örnek:

(   SECONDS=0
    while   sleep   "$((RANDOM%10))"
    do      sleep   "$((10-(SECONDS%10)))"
            echo    "$SECONDS"
    done
)

10
20
30
40
50
60
70
80
90
100

2
Sıfırlamayı önlemek SECONDSiçin yapın sleep "$((10-(($SECONDS-$start_time)%10)))". Döngüden start_time=$SECONDSönce yapmanız gerekecek .
ctrl-alt-delor

@richard - neden kaçınmalısınız?
mikeserv

çünkü bir gün bunu böyle bir döngü ile çağırdığınız bir senaryoda olacaksınız. Ve tüm günü neden düzgün çalışmadığını merak ederek geçireceksiniz. Kısacası, sıfırlarsanız yuvalamaz SECONDS. En son düzenlemenizde olduğu gibi bir alt kabuk oluşturmak da bu sorundan kaçınmalıdır.
ctrl-alt-delor

1
@richard - soru bir while truedöngü ile ilgili olduğundan, herhangi bir kabuk durumunun hayatta kalması bekleniyordu. Böyle bir döngüyü kendi bağlamında sarmak genellikle en iyi uygulamadır. Böyle bir durumda bunu yapmak trapuğruna yapmaktan daha fazla endişe $SECONDSduyarım.
mikeserv

Teşekkürler Mike, ben benzer bir şey yapmayı düşünüyordum (ama henüz nasıl özelliklerini bilmiyordum). Ama Sidhekin'in çözümü aynı şeyi yapıyor gibi görünüyor, değil mi? Daha iyi cevap konusunda karar verme yetkisine sahip değilim, ama bir şey seçmek zorunda olduğumu hissettim.
user1032531

3

Yalnızca BASH - Ayrıca komutunuz tarafından harcanan zamanı da hesaplayabilir ve 10'dan çıkarabilirsiniz:

TIMEFORMAT=$'%0R'
while true; do
    T=$({ time command; } 2>&1)
    sleep $(( 10-T ))

BASH adamından:

TIMEFORMAT Bu parametrenin değeri, ayrılmış zaman sözcüğü ile önceden eklenmiş boru hatları için zamanlama bilgilerinin nasıl görüntüleneceğini belirten bir biçim dizesi olarak kullanılır. % Karakteri, zaman değerine veya diğer bilgilere genişletilen bir kaçış dizisi sunar. Kaçış dizileri ve anlamları aşağıdaki gibidir; parantezler isteğe bağlı kısımları gösterir.
%% Değişmez%.
% [p] [l] R Geçen saniye cinsinden süre.
% [p] [l] U Kullanıcı modunda harcanan CPU saniye sayısı.
% [p] [l] S Sistem modunda harcanan CPU saniye sayısı.
% P (% U +% S) /% R olarak hesaplanan CPU yüzdesi.

İsteğe bağlı p, bir ondalık noktadan sonraki kesinlik ve kesirli basamak sayısını belirten bir basamaktır. 0 değeri ondalık nokta veya kesir çıktısının alınmamasına neden olur.

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.