Shell: Bir komutu `sleep` kullanmadan ertelemek mümkün mü?


21

Kullanmadan komutları geciktirmek için alternatifler, alternatifler veya bash püf noktaları var sleepmı? Örneğin, aşağıdaki komutu gerçekten uyku kullanmadan gerçekleştirme:

$ sleep 10 && echo "This is a test"

42
Neyin var sleep?
muru

5
Meraktan başka gerçek bir sebep yok. Bazı alternatif çözümler öğrenmenin ilginç olacağını düşündüm. Bir atolabileceğini düşünüyorum , ancak kullanım örnekleri bulamadım.
user321697

1
@ user321697 “at”, tek işleri planlamak içindir. atd servisi tarafından yürütüldüğünden kabuk betiğinizi duraklatmazlar. için bir kullanım durumu, belirtilen bir zamanda (zaman uyumsuz) bir şey yapması ve bittiğinde bir işaretleyici dosyası oluşturmasıdır; bu sırada komut dosyası, bir dosyanın döngü içinde görünmesini beklerken. senaryonuza SIGCONT göndermek için bir iş planlayarak ve ardından kendinize bir SIGSTOP göndererek senaryonuzu dondurarak benzer bir etki elde edebilirsiniz.
Grega Bremec

1
Buraya herkesin bir spinlock önermesini beklemek için geldim. Tüm cevaplar beni çok şaşırttı.
Daan van Hoek,

3
Re: "Merak" - in unix.stackexchange.com/help/dont-ask , bu şartı not "Sadece pratik, yanıtlanabilir sorunun sormalısınız Eğer karşılaştıkları gerçek sorunlara dayalı. " - Bu iyi-olmuştur Bu kılavuzun oldukça nadir görülen bir istisna haline geldiğine dair iddialara rağmen alınmış.
Charles Duffy

Yanıtlar:


17

Alternatifleriniz var sleep: Onlar atve cron. sleepBunların aksine, kaçmaları gereken süreyi belirtmeniz gerekir.

  • atdHizmetin yürüterek çalıştığından emin olun service atd status.
    Şimdi tarih 11:17 UTC; Eğer 11:25 UTC de bir komut çalıştırmak gerekiyorsa, sözdizimi: echo "This is a test" | at 11:25.
    Şimdi atd, varsayılan olarak, işlerin tamamlanmasının günlüğe kaydedilmeyeceğini unutmayın . Daha fazlası için bu bağlantıya bakın . Uygulamanızın kendi günlük kaydı olması daha iyidir.

  • İşleri zamanlayabilirsiniz cron, daha fazla bilgi için: man cronseçeneklerini görmek veya crontab -eyeni işler eklemek için. /var/log/cronişlerde yürütme hakkında bilgi için kontrol edilebilir.

FYI sleep system call mevcut yürütmeyi askıya alır ve kendisine iletilen argümanla zamanlamasını yapar.

DÜZENLE:

@Gaius'un bahsettiği gibi, komut için dakikalar da ekleyebilirsiniz. Fakat zamanın geldiğini atsöyleyelim 12:30:30ve şimdi zamanlayıcıyı çalıştırdınız now +1 minutes. 60 saniyeye karşılık gelen 1 dakika belirtilse de, işi yürütmeyi atbeklemekten 12:31:30ziyade işi yerine getirmeyi beklemiyor 12:31:00. Zaman birimleri olabilir minutes, hours, days, or weeks. Daha fazla bilgi içinman at

Örneğin: echo "ls" | at now +1 minutes


7
Bu doğru değil, bir işyerinde şimdi söyleyebilmeniz için +1 dakika, bir dakika içinde çalıştırmak için
Gaius

29

İle bashbuiltins, bunu yapabilirsiniz:

coproc read -t 10 && wait "$!" || true

Kullanmadan 10 saniye uyumak için sleep. Bunu coprocyapmak, readstdin'in hiçbir şeyin çıkamayacağı bir boru. || trueÇünkü waitçıkış durumu, errexitseçenek ayarlanmışsa kabuğun çıkmasına neden olacak bir SIGALRM teslimatını yansıtacaktır .

Diğer kabuklarda:

mkshve ksh93adres sleepyerleşik, (her ikisi de ayrıca desteklemektedir olsa orada başka bir şey kullanmadan hiçbir nokta read -t).

zshayrıca destekler read -t, ancak ayrıca yerleşik bir sargısı vardır select(), bu nedenle şunları da kullanabilirsiniz:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

İstediğiniz şey etkileşimli bir kabuk oturumundan çalıştırılacak şeyleri zamanlamaksa, içindeki zsh/schedmodülezsh de bakın .


Eğer düşünür müsünüz read -t 10 < /dev/zero || true?
Jeff Schaller

5
@JeffSchaller Meşgul bir döngü olduğu için bundan kaçınırdım.
Stéphane Chazelas

@ StéphaneChazelas Bunun yoğun bir döngü olmasını beklemem - Herhangi bir kabuğun olmasını beklerdim read (2) veya benzer bir şey kullanarak uygulanmasını (zaman aşımı ile okumanın bu soruya iyi bir cevap olacağını ima eder). Size karşı çıkmak yerine şaşkınlığı ifade ediyorum, ancak bununla ilgili daha fazla tartışmayı işaret edebilir misiniz?
Norman Gray

5
@NormanGray, /dev/zerosonsuz miktarda veri (NUL bayt) içeren bir dosyadır. Yani readbu 10 saniye boyunca olabildiğince çok okuyacak. Neyse ki, bashdeğişkenlerinde NUL baytlarının depolanmasını desteklemiyorsa, bu herhangi bir belleği kullanmayacak, ancak yine de CPU kaynaklarını etkileyecektir.
Stéphane Chazelas 19:18

1
@NormanGray, bir uçbirimden çalıştırıldığında /dev/stdouttty aygıtı olur, bu nedenle yan etkileri olur (arka planda çalışırsa betiği durdurmak gibi) ve kullanıcı mesela girerse basarsa geri döner. read -t 10 /dev/stdout | :Linux üzerinde çalışacak, ancak sadece Linux için, coprocişletim sistemi ne olursa olsun çalışmalı.
Stéphane Chazelas 19:18

7

Başka fikirler.

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null

1
Zamanımı / zaman aşımı fikrimi "çaldın" .... +1
Rui F Ribeiro

1
Ohhhh, teşekkürler, uykusuz bir durumdaydım, üst harika!
Fire-Dragon-DoL

6

Standart olmayan -t delayseçeneğinin kullanılmasını öneren cevaplar olduğu için read, standart bir kabukta zaman aşımına uğramış bir okuma yapmanın bir yolu:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

Argümanı stty timesaniyenin onda birinde.


5

Bash yerleşik değişkenini $SECONDSve meşgul döngüsünü kullanma:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done

2
Yani olur gerçi 9 ila 10 saniye içinde bir yere değişen sürelerde etkisi duraklama (nedeniyle bir hatabash ; zshve mkshbenzer sorunları vardı ama sonra düzeltilen)
Stéphane Chazelas

7
Isı yapmak için iyi bir yol.
ctrl-alt-delor,

6
ilk defa sıcak hava dolu olmakla suçlanmayacağım! :)
Jeff Schaller

4

Kitaptaki en eski numara:

read && echo "This is a test"

Sadece vur Enterve devam edecek!


Bu işlemin etkileşimi serbest veya arka planda yapması gerekiyorsa olmaz mı?
ss_iwe

Doğru: Ancak bu, orijinal soruya göre OP'nin gerekliliklerinden biri değildi, bu yüzden hala geçerli bir cevap ... ;-)> :-)
Fabby

1
OP özellikle bir örnek verir (ile sleep) ve olmadan eşdeğer bir alternatif ister. Bu yüzden readayrıştırma, üzgünüm. ;)
AnoE

@Hayır Stéphane'nin cevabı elbette en iyisi, benimki sadece en eskisi --- press «enter» to continue --- ;-)
Fabby

4

BASIC çalıştıran mikrobilgisayarların günlerinde gecikmeler genellikle boş bir döngü ile gerçekleştirildi:

FOR I = 1 TO 10000:NEXT

Aynı prensip bir kabuk betiğine bir gecikme eklemek için kullanılabilir:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

Tabii ki, bu yaklaşımla ilgili sorun, gecikme süresinin işlemcinin hızına göre makineden makineye değişeceğidir (hatta aynı makinede farklı yükler altında bile değişebilir). Aksine sleep, muhtemelen CPU'nuzu (veya çekirdeklerinden birini) de maksimuma çıkarır.


2
Isı yapmak için iyi bir yol.
ctrl-alt-delor,

2
Gecikmeli döngüler, Unix benzeri bir işletim sistemi çalıştırabilen herhangi bir modern CPU'da en kısa uyku (bir aygıt sürücüsünde birkaç nanosaniye veya saat döngüsü) dışında herhangi bir şey için korkunç bir fikirdir. yani, çok kısa bir uyku, bir başka işlem planlamak ya da zamanlayıcı kesilmesinden önce uyanmadan önce düşük güçte bir uyku durumuna girmek gibi, CPU'nun beklerken başka bir şey yapmasını sağlayamazsınız. Dinamik CPU frekansı, hızlanma hızından önce düşük saat hızlarında çok daha uzun süre uyuma ihtimali olan asgari bir gecikme dışında, saniyede sayım için bir gecikme döngüsünü bile kalibre etmeyi imkansız kılar.
Peter Cordes

Eski bilgisayarlarda iş yüküne daha az bağımlı olan bir güç tüketimi vardı. Modern CPU'ların, çipin farklı kısımlarını eritmemek için mümkün olduğunca dinamik olarak kapatması gerekir (örn. Sadece tamsayı kodu çalışırken FPU veya SIMD yürütme birimlerinin parçalarını kapatın veya en azından çipin parçalarına saat sinyalini girin) Bunun değişmesi gerekmiyor). Ayrıca, boşta iken (zamanlayıcı kesintilerini bekleyen sonsuz bir döngüde eğirmek yerine) eğirmek yerine düşük güçte bir uyku durumuna girmek de bahsettiğiniz eski bilgisayarlardan daha yakındır.
Peter Cordes

CPU geçmişi hakkında daha fazla bilgi için, bkz. Modern Mikroişlemciler A 90 Dakika Kılavuzu! - lighterra.com/papers/modernmicroprocessors .
Peter Cordes

3

Yerleşik yoktur, sleep( aynı olmadıkça) sleepile aynıdır . Ancak bekleyecek başka komutlar da var.

Birkaç içerir.

  • atve cron: belirli bir zamanda görevleri zamanlamak için kullanılır.

  • inotifywait: bir dosyayı beklemek için kullanılır ya da değiştirilecek / kaldırılmış / eklenmiş / etc


Bunun için teşekkürler. İle zamanlanmış bir görev (örneğin, 10 saniye) gerçekleştirmek için bir örnek verebilir misiniz at?
user321697

1
bir düzenleme ve bir artı! ;-)
Fabby

crongörevleri sakla crontab, tamam mı? atZamanlanmış verileri nerede depolar?
user321697

@ user321697 Zaten burada
Fabby

Maalesef Q'ya düzenlemenizi geri geri almak için: Tüm ... en basit cevabı geçersiz olur OP Sorunun ana amacını değiştirdi ¯ \ _ (ツ) _ / ¯
Fabby

3

Windows ve Partiler Ülkesi'nden bir klasik:

ping -c 11 localhost >/dev/null && echo "This is a test"

Güvenlik duvarı veya ad sisteminin yanlış yapılandırılması, zorlu bir şekilde önemli bir ek gecikmeye neden olabilir.
spektrumlar

1
127.0.0.1 ... @spectras
AnoE

1
Neyse ki artık gerekli değil, çünkü Windows artık yerel olarak uykuyu destekliyor.
Baldrickk

1
@ AnoE> güvenlik duvarı bölümünü değil ad sistemi bölümünü çözer. Yaygın olmasa da, yerel arayüze ping sessizce düşürmek için yapılandırılabilir. Bu, ping'in daha uzun süre beklemesine neden olur.
spektrumlar

AC

0

Etkileşimli olarak bir dosyada yeni bir satır beklemek istiyorsanız, ardından

tail -f
.

Bir dosya sisteminde değişiklik mi bekleniyor? O zaman örneğin kullanın

inotify / inoticoming
.

"Bekle" ile ne kastettiğinize bağlı olarak başka seçenekler de var.

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.