Linux altında askıya alınmış durumda bir işlemi nasıl başlatırım?


19

Pratik olarak, Ctrl+Zbaşladıktan hemen sonra bastırmışım gibi davranan bir sürece ihtiyacım var .

Umarım, böyle bir şeyi bir kabuk betiği kullanarak yapmak mümkündür.

(Ayrıca, ortaya çıkan PID'yi bilmek harika olurdu, bu yüzden daha sonra sürece devam edebilirim.)

Yanıtlar:


7

Bir işleme başladıktan sonra askıya almak için SIGSTOP gönderebilirsiniz. Devam etmek için SIGCONT'u gönderin. Bence bu küçük senaryo size yardımcı olabilir

#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID

İşlemi çalıştırır (parametre olarak komut gönder), askıya alır, işlem kimliğini yazdırır ve bitene kadar bekler.


1
Sonunda devam etmek için değiştirdim: [enter] #!/bin/bash [enter] $@ & [enter] PID=$! [enter] kill -STOP $PID [enter] echo "Suspended: $PID, press ENTER to continue it" [enter] read [enter] kill -CONT $PID [enter] wait $PID [enter]echo
java.is.for.desktop

7
Bildiğiniz gibi, durdurma sinyalini ona gönderme şansınız bile olmadan alt işlem bitebilir.
MikeyB

16
Yarışlarda başka bir gün.
ctrl-alt-delor

23

Süreci hangi ortamdan oluşturuyorsunuz?

Bunu C kodu gibi bir ortamdan yapıyorsanız, çatalla () ve sonra çocukta, exec () işleminden önce kendinize bir SIGSTOP göndererek daha fazla yürütmeyi engelleyebilirsiniz.

Daha genel bir çözüm (muhtemelen en iyisi) bunu yapan bir saplama oluşturmak olacaktır. Yani saplama programı:

  • Gerçek programın adı ve argümanlarından oluşan argümanları alın
  • kendine bir SIGSTOP gönder
  • exec () gerçek programı uygun argümanlarla

Bu, yeni işlemin ona bir sinyal göndermeden önce çok fazla ilerlemesiyle ilgili her türlü yarış koşulundan kaçınmanızı sağlayacaktır.


Kabuk için bir örnek:

#!/bin/bash
kill -STOP $$
exec "$@"

Ve yukarıdaki codez kullanarak:

michael@challenger:~$ ./stopcall.sh ls -al stopcall.sh

[1]+  Stopped                 ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ jobs -l
[1]+ 23143 Stopped (signal)        ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ kill -CONT 23143; sleep 1
-rwxr-xr-x 1 michael users 36 2011-07-24 22:48 stopcall.sh
[1]+  Done                    ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ 

jobs -lPID gösterir. Ancak bir kabuktan yapıyorsanız, doğrudan PID'ye ihtiyacınız yoktur. Sadece şunları yapabilirsiniz: kill -CONT %1(sadece bir işiniz olduğunu varsayarsak).

Birden fazla iş ile mi yapıyorsunuz? Okuyucu için bir egzersiz olarak bırakıldı :)


Bunu bir kabuk komut dosyasından yapmayı umuyordum ...
java.is.for.desktop

Harika, bu yüzden bunu bir kabuk komut dosyasından yapmak istediğiniz için, saplama programını kullanın.
MikeyB

20

MikeyB'nin cevabı doğrudur. Gönderen bu soruya süper burada, daha kısa ve öz sürümü:

( kill -SIGSTOP $BASHPID; exec my_command ) &

Bunu anlamak için, işlemlerin unix'te nasıl başlatıldığını anlamalıdır: execsistem çağrısı , şu anda çalışan programı yenisiyle değiştirerek mevcut PID'yi korur. Bu arada Yani oluşturulan bağımsız bir süreç ilk etmektir forkve ardından execistenilen program ile çocuk çalışmakta olan süreci yerine.

Bu kabuk komutunun içeriği:

  1. Parantezler (...)bir alt kabuk başlatır: başka bir BASH örneği.
  2. killKomut süspansiyon haline koyar Bu işleme göre, durdurma sinyali gönderir.
  3. İşlemin devam etmesine izin verir vermez ( CONTsinyali göndererek ), execkomut işlemin kendisini istediğiniz programla değiştirmesine neden olur . my_commandalt kabuğun orijinal PID'sini tutar.
  4. $!Sürecin PID'sini almak için değişkeni kullanabilirsiniz .

2
Bunu seviyorum, temelde doğru olduğu için (sadece -s STOPyerine kullanmak zorunda kaldım -SIGSTOP). Hala merak ediyorum: neden bunun $BASHPIDyerine olması gerekiyor $$? (Farkı gerçekten anlamayabilirim).
Hibou57

1
İçin $$vs $BASHPID, ben ise eski değil, ikincisi alt kabuğun PID olduğunu kontrol edin. Komik bir sorun var: bir bash betiğinde ipucu uygulamak, çoğu zaman başarısız olur ve böyle bir şey yapmak zorundayım: PID=$!; ps -p $PID; kill -s CONT $PID;ps -p $PIDparçayı kaldırırsam başarısız olur : süreç herhangi bir hata mesajı olmadan kayboluyor (öldürüldü?) Gibi görünüyor . Etkileşimli bir kabuktan sorun yok, sorun sadece koddan kaynaklanıyor. Bu çok gizemli.
Hibou57

Bu çözümü my_command dosya tanımlayıcılarını listelemek için kullanmaya çalıştım. ( goo.gl/cNbUE8 ) ancak tanımlayıcılar hala aynı değil my_command'ın ne olduğu önemli değil.
rasty.g

$BASHPIDBash dışındaki mermileri değiştirme seçenekleri için buraya
Jakob
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.