Kabuk betiğini duraklatmak için herhangi bir tuşa basın, devam etmek için tekrar basın


11

Dosyaları kopyalayan ve her birinden sonra ilerlemesini yansıtan bir API'yi test etmek için bir kabuk komut dosyası yazdım.

Her kopya arasında iki saniyelik bir uyku var, bu yüzden daha derin testlere izin vermek için komut dosyasını duraklatmak için herhangi bir tuşa basma özelliğini eklemek istiyorum. Ardından, devam etmek için herhangi bir tuşa basın.

Bunu mümkün olduğunca az satıra nasıl ekleyebilirim?

Yanıtlar:


12

Senaryonuza bir şey eklemenize gerek yok. Kabuk böyle bir işlevselliğe izin verir.

  • Komut dosyanızı bir terminalde başlatın.
  • Süre çalışıyor ve terminal kullanımını engelliyor ctrl- z. Terminal tekrar serbest bırakılır ve işlemin durdurulduğunu belirten bir mesaj görürsünüz. (Şimdi durma durumunda T, durdu)
  • Şimdi ne istersen yap. Ayrıca diğer işlemleri / komut dosyalarını başlatabilir ve ctrl- ile durdurabilirsiniz z.
  • Tip jobsterminal veya liste tüm durdurulmuş işlerde.
  • Komut dosyanızın devam etmesine izin vermek için fg(ön plan) yazın. İşi ön plan süreç grubuna geri döndürür ve işler çalışmaya devam eder.

Bir örneğe bakın:

root@host:~$ sleep 10 # sleep for 10 seconds
^Z
[1]+  Stopped                 sleep 10
root@host:~$ jobs # list all stopped jobs
[1]+  Stopped                 sleep 10
root@host:~$ fg # continue the job
sleep 10
root@host:~$ # job has finished

Dediğin gibi, eğer koşup sleep 10; notify-send hellodurmak için CTRL + Z tuşlarına basarsam, notify-send helloçalıştır. ikinci komut yürütülüyorsa nasıl olur da ilk işlem durdurulur? Bundan sonra, eğer fgi ikinci komut zaten yürütüldüğünden beri açık olan bir şey göremiyorsanız
Edward Torvalds

@edwardtorvalds çünkü iki komut ayrı. Bir senaryoda alt kabukta olabilirlerdi. Bunları basit bir komut dosyasına yazın ve komut dosyasını yürütün. Sonra durdurmak için ctrl-z ve ilk bitene kadar ikinci komutun yürütülmediğini göreceksiniz. Yazmak cmd; cmd; cmd;yazmak gibidir cmd <newline> cmd <newline> .... ( cmd; cmd; cmd; )Yazabileceğiniz bir senaryoya alternatif olarak, senaryo gibi davranır, tarafından oluşturulan alt kabuğun bacuse(
chaos

ben de denedim sleep 10. 3 saniye sonra CTRL + Z tuşlarına bastığımda ve birkaç saniye sonra devam ettiğimde uyku komutunun 7 saniyeden daha kısa sürede öldüğünü fark ettiğimde. Bu, söylediklerinizin tam tersidir, çünkü komut nişleri durduğundan arka planda çalışır.
Edward Torvalds

@edwardtorvalds Bunu da fark ettim ... Mantıklı değil. Ben straced sleepkomuta ve kullanılan sistem çağrısı olduğunu öğrendim nanosleep(). Sistem çağrısının tanımlanmış bir davranışı gibi görünüyor nanosleep. restart_syscall()kesilen sistem çağrısını, daha önce geçen süreyi (işlemin bir sinyal tarafından durdurulduğu zaman dahil) uygun olarak ayarlanmış bir zaman argümanı ile yeniden başlatır. Bu sayfayı
kaos

@ Chaos yanıtını tamamlamak için birkaç not (bunları dahil etmekten çekinmeyin): ctrl-Z yaptığınızda, iş askıya alınır ("durdurulur"), bu yüzden şu anda çalışmaz, devam etmeye karar vermenizi bekler ön planda (ör:) fg %1veya arka planda (ör:) bg %1. (işler sadece 1 sayı verirse, örneğin örnek kaosun gösterdiği gibi sadece 1 askıya alınmış işlem [1]+ stopped sleep 10varsa : yalnızca , %nparçayı atlayabilirsiniz . ile: %n(ör: fg %2 ön planda% 2 özgeçmişe sahip olmak için))
Olivier Dulac

6

Betiğin içinde kalırken betiği sadece duraklatmak istiyorsanız, uyku yerine read komutunu kullanabilirsiniz.

Kullanabilirsiniz

read -tokumaya devam
read -netmek için bir karakter zaman aşımı ayarlamak için (etkili bir şekilde herhangi bir tuşa basın)

Herhangi bir kod sağlamadığınız için aşağıda kodun nasıl kullanılabileceğine bir örnek verilmiştir.
Q düğmesine basılırsa read -n1, bir tuşa basılana kadar komut dosyasının devam etmesini önler.
Bir tuşa basıldığında kontrol sıfırlanır ve kod döngüde normal şekilde devam eder.

while [[ true ]]; do
    read -t2 -n1 check
    if [[ $check == "q" ]];then
        echo "pressed"
        read -n1
        check=""
    else
        echo "not pressed"
    fi
echo "Doing Something"
done

Yazmanın ekran çıktısını karıştırmasını önlemek stty -echoiçin bölümün başına ve stty echosonuna da ekleyebilirsiniz .


mikeserv Op okunan şeyleri umursamıyor sanmıyorum, sadece komut dosyası duraklatmak ve devam ettirmek istiyorum, terminal ayarlarını da kaydederek ne demek istiyorsun, ben sadece bir tane değiştiriyorum, bu yüzden biraz abartılı görünüyor.

1
@mikeserv ahh doğru, ben sadece tüm stdin kullanıcıdan geliyor olacağını varsayıyordum.

1

İle ddbir dosyadan tek bir baytı güvenilir bir şekilde okuyabilirsiniz. İle bir terminal okuma ve bir saniyenin onda biri olarak bir çıkış nitelendirmek için sttybir mindizi bayt ayarlayabilirsiniz time. Bu ikisini birleştirin ve sleepbence tamamen olmadan yapabilirsiniz ve sadece terminalin okuma zaman aşımının sizin için işi yapmasına izin verin:

s=$(stty -g </dev/tty)
(while stty raw -echo isig time 20 min 0;test -z "$(
dd bs=1 count=1 2>/dev/null; stty "$s")" || (exec sh)
do echo "$SECONDS:" do your stuff here maybe                             
   echo  no sleep necessary, I think                                                          
   [ "$((i+=1))" -gt 10 ] && exit                                                             
done       
) </dev/tty

whileDenemeniz için alay ettiğim küçük bir örnek döngü. Her iki saniyede bir dd, ' stdinyeniden yönlendirildi' /dev/ttyve whiledöngü döngüleri okuma girişiminde zaman aşımına uğrar. O veya dd does not zaman aşımı Bir tuşa basın - çünkü bu durumda etkileşimli bir kabuk çağrılır.

İşte bir test çalıştırması - her satırın başına yazdırılan sayılar kabuk değişkeninin değeridir $SECONDS:

273315: do your stuff here maybe
no sleep necessary, I think
273317: do your stuff here maybe
no sleep necessary, I think
273319: do your stuff here maybe
no sleep necessary, I think
273321: do your stuff here maybe
no sleep necessary, I think
sh-4.3$ : if you press a key you get an interactive shell
sh-4.3$ : this example loop quits after ten iterations
sh-4.3$ : or if this shell exits with a non-zero exit status
sh-4.3$ : and speaking of which, to do so you just...
sh-4.3$ exit
exit
273385: do your stuff here maybe
no sleep necessary, I think
273387: do your stuff here maybe
no sleep necessary, I think
273389: do your stuff here maybe
no sleep necessary, I think
273391: do your stuff here maybe
no sleep necessary, I think
273393: do your stuff here maybe
no sleep necessary, I think
273395: do your stuff here maybe
no sleep necessary, I think
273397: do your stuff here maybe
no sleep necessary, I think

stty saneStty ayarını değiştirdikten sonra kullanmamalısınız , yanlış olabilirim ama onları herhangi bir yere sıfırlamış gibi görünmüyor mu?

@Jidder - hayır Ben komut dosyasının üstündeki terminalin durumunu kaydedin s=$(stty -g </dev/tty). Aradıktan hemen sonra ddile geri yüklerim stty "$s". Terminal durumu alt kabukları umursamaz ve bu nedenle bu ayarlar üst kabuktan bağımsız olarak yapışır. stty saneille de yapmak istediğiniz şey değildir - devleti sanebu noktada olduğunu varsaymak yerine, onu bulduğunuz şekilde yeniden kurmak daha iyidir . Eğer geri yüklemek echoolmasaydı o s her yerde olurdu. Bunun neden bu kadar geç geldiğimi anlamak - teste başladığımda cevabınız burada değildi.
mikeserv
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.