Belirli bir süre geçtikten sonra Çalıştır komutu?


24

Uzun bir işlem yürütüyorsam, zamana dayalı bazı komutları uygulayabilmemin bir yolu var mı?

Örneğin, yaklaşık 10 dakika süren çok uzun bir işlem yapıyorum.

5 dakika sonra ayrı bir komut çalıştırmak istiyorum. Örnek olarak, ayrı komut şöyle olabilir:echo 5 minutes complete

(Not: Komutun tamamlanması yönünde ilerleme istemiyorum, ancak belirtilen aralıklardan sonra yürütülen komutlar için.)

Mümkün mü?


1
Çoğu zaman, bir sürecin ne kadar süreceğini önceden bilmiyorsunuz.
choroba

Ne demek "zaman tabanlı komutlar"? Bir ilerleme çubuğu oluşturmak ister misiniz? Sorunuzun şu anki ifadesine dayanarak, sadece uzun süre çalışan komutu arka planda tutabilir ve ardından sistem saatini görüntüleyebilirsiniz. Lütfen açıkla.
Joker,

@Wildcard soruyu açıklığa kavuşturdum. Bir ilerleme çubuğu değil. Bazı aralıklarla komutları yerine getirecek
Aniket Bhattacharyea

1
"5 dakika tamamlandı" yankı yapmak tuhaf bir şey. "5 dakika geçti" değil mi? "Zaman _____" değil mi? Başka bir rastgele komut çalıştırılmadan önce, uzun süre çalışan komutunuzun başlatıldığı zamandan belirli bir zaman aralığının geçtiğinden emin olmak ister misiniz? Eğer öyleyse, neden sadece kaçmıyorsun longcommand & sleep 300 && command-to-do-after-five-minutes? (Aslında aradığınız şey muhtemelen budur.) Açıklamanın yeterli olmadığını unutmayın, çünkü yarasanın hemen üzerinde iki adet saat ilerleme çubuğu uygulaması var.
Wildcard

Yanıtlar:


29

Sadece koş:

long-command & sleep 300; do-this-after-five-minutes

do-this-after-five-minutesBeş dakika sonra çalıştırmak alacak. long-commandArka planda çalışan edilecektir.


10
Genelde kullanıyorum sleep 5m && foobar, bu yüzden fikrimi değiştirir ve ^ C the sleep, sonraki komut çalışmaz.
Peter Cordes

@PeterCordes, örneğin sleep 3; lsve ile test ettiğimde ^Cikinci komut yine de çalışmıyor. Neden olduğundan emin değil ve belki etkileşimli olmayan bir kabukta farklı şekilde çalışıyor olabilir?
Joker,

1
@PeterCordes Tam değil - kabuk başına farklılık göstermediği sürece. Ne zaman sleep 5m && echouyuyor sen askıya aldığımızda, yalnızca sleepkomut askıya alınır. Komut satırının geri kalanı çalışır, ancak sleepaskıya alındığından, başarıyla çıkmadı ve sonraki kısım &&atlandı. Askıya almayı deneyin sleep 5 || echo hellove hellobastıktan hemen sonra gösterilir ^Z.
hvd

1
@hvd: Evet, haklısın ve ben yine hatalıyım>. <, bash4 kullanarak. Anlaşılan, & & bir getto olarak gitmenin at(1), sleep 30m && mplayer something.mp3alarm hatırlatması gibi şeyler için veya sleep 90m && fgdaha sonra disk yoğun bir komutu sürdürmenin yolu olduğuna karar verdiğimden bu yana çok uzun zaman geçti . Aslında sleep 5m && echo hellogüzel, çünkü aşağıdaki komutu hiç çalıştırmadan ^Zaskıya alınıyor sleep. Tüm bileşik komutunu askıya almak / devam ettirmek istiyorsanız, uyku çıkmadan önce bile kullanın ( sleep 2 && echo hello ).
Peter Cordes

@hvd: &&Deyim, uyku çalıştıktan hemen sonra süreci öldürmediğinizden kesinlikle emin olmanızı sağlar (çünkü ^Za riskini almak yerine komutu çalıştıramazsınız ^C). Bu, sleep && fgya da sleep && bgkullanım durumunda, devam ettirilen komutun yavaş bir şeyden kısmen geçtiği durumlarda faydalıdır .
Peter Cordes

5

Bu betiği kullanabilirsiniz:

#!/bin/bash

TEMPFILE="$(mktemp)"
STARTTIME="$(date +%s)"
(./longprocess; rm -f "$TEMPFILE") &
while [ -f "$TEMPFILE" ]; do
    sleep 1s
    NOW="$(date +%s)"
    if (( (NOW-STARTTIME) % 300 == 0 )); then
        echo "$(( (NOW-STARTTIME)/60 )) minute(s) elapsed"
    fi
done
echo "Done!!!"

Bu sizin yürütür longprocessbir de sub-shellvarlığını ve sonra monitörler daha önce oluşturulan 'kilit' dosyası.


2
Kontrol man bashedin SECONDS. Sen ayarlayabilirsiniz SECONDS=0komut başlangıcında ve sadece üstünü kontrol etmek veya 300 veya setine eşit SECONDS=$((date +%s))ve kullanma unutmak date... Betiğinizde tekrar

@yeti, ipucu için teşekkürler, bunu bilmiyordum.
Serge,

@yeti, sleep 1sher zaman öncekinden bir saniye sonra her zaman sonra zamana güvenmek istiyorsan sleep 1s... programcıların zamana inandıkları Sahteliklerin kurbanı oldun . (Her ne kadar bu durumda, sadece bir karma işareti ilerleme çubuğu veya başka bir şey de gösterebilirsiniz.)
Wildcard

@Wildcard ... Ben hiç bahsetmedim sleep!

@yeti, haklısın. Bahşiş için teşekkürler SECONDS! :)
Wildcard

4

Bunun için bir astar var:

( ( sleep $TIMEOUT ; echo "5 minutes complete") & $COMMAND )

Senin durumunda TIMEOUT = 5m ve KOMUT uzun komuttur.

Ayrıca bu yazıya verdiğim cevaba bakın 'service network restart' ile zaman aşımı


Ön planda bir alt kabuk başlatmak ve ardından komutu uygulamak gereksiz yere karmaşık görünüyor. Dış parantezleri ve exec'i kaldırırdım.
glenn jackman,

1
@ glennjackman Bu yol, ana (en dıştaki) alt kabuğa CTRL + C (örneğin) göndererek tüm prosedürü öldürebilir.
coffeMug

1
Ama exec kullanarak, artık bir deniz kabuğu yok, sadece komutunuz var. Komutun ailesi, tıpkı bir alt kabuk kullanmamışsınız gibi komut dosyasını çalıştıran kabuktur.
glenn jackman

3
#! /bin/bash

( sleep 4 ) & # <-- The long running process.

seconds=1
while jobs %1 &>/dev/null ; do
    echo $((seconds++)) seconds complete
    sleep 1    
done
echo Done.

jobs %1 % 1 işi durduktan sonra başarısız olur.

Daha uzun süreler için, $ saniye gerçek zamanlı ile senkronize olamayacağını unutmayın. Başlangıç ​​zamanını kaydetmek ve gerçek zamanla farkı hesaplamak daha iyidir.

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.