İşlem kimliğinin (PID) var olup olmadığı nasıl kontrol edilir


184

Bir bash betiğinde, aşağıdakileri yapmak istiyorum (sözde kodda):

if [ a process exists with $PID ]; then

    kill $PID 

fi

Koşullu ifade için uygun ifade nedir?

Yanıtlar:


182

Bir sürecin varlığını kontrol etmek için şunu kullanın:

kill -0 $pid

Ama @unwind'in söylediği gibi, yine de öldüreceksen,

kill $pid

ya da bir yarış durumunuz olacak.

Metin çıkışını yok saymak killve çıkış koduna göre bir şey yapmak istiyorsanız,

if ! kill $pid > /dev/null 2>&1; then
    echo "Could not send SIGTERM to process $pid" >&2
fi

1
man sayfasına bakıldığında kill -0: "çıkış kodu bir sinyalin gönderilip gönderilemeyeceğini gösterir". Peki bu aslında bir süreci mi öldürüyor yoksa sadece öldürülüp öldürülemeyeceğini söylüyor mu?
Richard H

24
killsürecin öldürülmesi gerekmediği için biraz yanlış adlandırılmıştır. Sadece sürece bir sinyal gönderir. sona erdirmek için bir talimat olan SIGTERM sinyalini işleme gönderen 15'e kill $PIDeşdeğerdir kill -15 $PID. Bir sinyal 0 yoktur, bu killsadece sürece bir sinyalin gönderilip gönderilemeyeceğini kontrol etmeyi söyleyen özel bir değerdir ; Bkz. Linux.die.net/man/2/kill ve linux.die.net/man/7/signal
Christoffer Hammarström

43
Bu sorun, işlemin çalışmakta olan kullanıcının sahibi olmaması durumunda kill -0 çağrısı yapma izniniz olmayabilir. Sinyal gönderme izniniz olmasa bile, işlem durumunu görmenizi sağlayan ps -p $ PID> / dev / null 2> & 1'i kullanmak daha iyidir.
mckoss

6
@mckoss: Bu durumda yine de öldüremez.
Christoffer Hammarström

2
Yani, sanırım - kullanmak için kill -0, aslında, bunu yapmak zorundayım: kill -0 25667 ; echo $?- ve sonra bir 0iade alırsam, bu PID ile süreç öldürülebilir; Proses PID (diyelim) yoksa ve, $?olacak 1bir arıza olduğunu belirten. Bu doğru mu?
sdaau

264

En iyi yol:

if ps -p $PID > /dev/null
then
   echo "$PID is running"
   # Do something knowing the pid exists, i.e. the process with $PID is running
fi

Sorun:

kill -0 $PID

pid çalışıyor olsa ve onu öldürme izniniz olmasa bile çıkış kodunun sıfır olmamasıdır. Örneğin:

kill -0 1

ve

kill -0 $non-running-pid

normal bir kullanıcı için ayırt edilemeyen (sıfır olmayan) bir çıkış koduna sahip olmakla birlikte, başlatma işlemi (PID 1) kesinlikle çalışıyor.

TARTIŞMA

Testin gövdesi bir "öldürme" ise, öldürme ve yarış koşullarını tartışan cevaplar kesinlikle doğrudur. " Bash'da bir PID varlığını nasıl test edersiniz " genelini aramaya geldim .

/ Proc yöntemi ilginçtir, ancak bir anlamda "ps" komut soyutlamasının ruhunu kırar, yani / proc'a gitmenize gerek yoktur çünkü Linus "exe" dosyasını başka bir şey olarak adlandırmaya karar verirse ne olur?


1
ps -p her zaman benim için 0 durumunu döndürür
IttayD

1
ps -p #### Ubuntu 14.04, +1 teşekkürler benim için iyi çalıştı!
Ligemer

3
ps -p her zaman os x'de durum kodunu 0 döndürür, çünkü çalışan herhangi bir işlemle eşleşmediğinde boş bir süreç listesi yazdırır
Douglas Correa

MacOS Sierra'da bunun işe yaradığını doğrulayabilirim. Ayrıca, -pen azından bu durumda gereksizdir. ps $PIDaynı sonucu verir.
user137369

Taşınabilirlik / proc kullanmaktan kaçınmak için iyi bir nedendir, ancak linux'un ABI'sını kırmak özellikle endişe duyacağım bir senaryo değildir.
David Roundy

67
if [ -n "$PID" -a -e /proc/$PID ]; then
    echo "process exists"
fi

veya

if [ -n "$(ps -p $PID -o pid=)" ]

İkinci formda, -o pid=yalnızca üst bilgisi olmayan işlem kimliği sütununu görüntülemek için bir çıktı biçimidir. Tırnaklar boş olmayan dize operatörünün geçerli sonuç vermesi için gereklidir-n .


1
İkinci yöntem, Mac'te de ek bir artı olarak çalışır (Mac OS X'in / proc FS'si yoktur). Ancak, bir altkabuk kullanmaktan kaçınmak ve Mac ve Linux hem bu kullanabilirsiniz:if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
Will

Ne yazık ki, psseçenekler ve özellikler platformlar arasında değişiklik gösterme eğilimindedir, bu yüzden hala tamamen taşınabilir değildir.
tripleee

1
eğer $PIDboşsa dizin hala var olduğundan hala [ -e /proc/$PID ]true değerini döndürür /proc/.
Magne

34

pskomutu ile -p $PIDbunu yapabilirsiniz:

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs

11

İki yolunuz var:

Dizüstü bilgisayarımda belirli bir uygulamayı arayarak başlayalım:

[root@pinky:~]# ps fax | grep mozilla
 3358 ?        S      0:00  \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2    S+     0:00              \_ grep mozilla

Tüm örnekler şimdi PID 3358'i arayacaktır.

Birinci yol : İkinci sütunda PID için "ps aux" ve grep komutunu çalıştırın. Bu örnekte firefox'u ve ardından PID'sini arıyorum:

[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358

Yani kodunuz:

if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
    kill $PID 
fi

İkinci yol : Sadece /proc/$PIDdizinde bir şey arayın . Bu örnekte "exe" kullanıyorum, ancak başka bir şey kullanabilirsiniz.

[root@pinky:~]# ls -l /proc/3358/exe 
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash

Yani kodunuz:

if [ -f /proc/$PID/exe ]; then
    kill $PID 
fi

BTW: sorun kill -9 $PID || truenedir?


DÜZENLE:

Birkaç ay boyunca düşündükten sonra .. (yaklaşık 24 ...) burada verdiğim orijinal fikir güzel bir hack, ama son derece dayanılmaz. Linux'un birkaç uygulama ayrıntısını öğretirken, Mac, Solaris veya * BSD üzerinde çalışmaz. Hatta gelecekteki Linux çekirdeklerinde bile başarısız olabilir. Lütfen - diğer yanıtlarda açıklandığı gibi "ps" kullanın.


en azından öldür -9 kısmı yanlış görünüyor (alt süreçleri öldürmez)
nurettin

İlk yolu kullanırken neden [: eksik `] 'i alıyorum?
tenmiles

1
/proc/$PID/exenormal bir dosya değil. Yani, [ -f /proc/$PID/exe ]her zaman bir falsesonuç döndürür . Deneyin [ -h /proc/$PID/exe ].
Alexander Yancharuk

8

İstediğin gibi görünüyor

wait $PID

$pidbittiğinde geri döner .

Aksi takdirde kullanabilirsiniz

ps -p $PID

Sürecin hala hayatta olup olmadığını kontrol etmek için (bu, kill -0 $pidpid'e sahip olmasanız bile çalışacağından daha etkilidir ).


1
beklemek o kadar etkili değildir, çünkü işlem şu anki kabuğun çocuğu olmalıdır ya da aşağıdakileri verecektir:pid 123 is not a child of this shell
Calumah

7

Bence bu yarış koşullarına açılan kötü bir çözüm. İşlem testinizle öldürme çağrınız arasında ölürse ne olur? Sonra öldürme başarısız olur. Öyleyse neden her durumda öldürmeyi denemiyorsunuz ve nasıl gittiğini öğrenmek için dönüş değerini kontrol etmiyorsunuz?


+1 maalesef kill (1) 'in çıkış kodu farklı hata durumlarını ayırt etmiyor (sinyal vermediği her işlem için çıkış değerini bir artırıyor gibi görünüyor). OP kendi kill (2) paketleyicisini yazmayı düşünmezse, başarısız bir kill (2) çağrısından sonra ERRNO değerine göre farklı değerlerle çıkmasını sağlayabilir.
sadece birileri

Şu anda ben sadece kontrol ile öldürmek -9 yapıyorum - ben sadece bir hata "süreç yok" yoksa çok düzenli olmayan bir hata alıyorum. Ne olduğunu nasıl test ederim?
Richard H

14
Dikkatsizce yapma kill -9. Bu, işlemi anında öldürür ve kendi kendini temizleme şansı vermez. Bunun yerine buna killeşdeğer kullanın kill -15. Bu işe yaramazsa, nedenini ve sadece son çare kullanımı olarak öğrenmelisiniz kill -9.
Christoffer Hammarström

0

Burada PID .pid adlı bir dosyada saklar (bu tür / run / ... gibi) ve sadece yürütülmüyorsa sadece komut dosyası yürütmek.

#!/bin/bash
if [ -f .pid ]; then
  read pid < .pid
  echo $pid
  ps -p $pid > /dev/null
  r=$?
  if [ $r -eq 0 ]; then
    echo "$pid is currently running, not executing $0 twice, exiting now..."
    exit 1
  fi
fi

echo $$ > .pid

# do things here

rm .pid

not: pid'in nasıl çağrıldığını kontrol etmediği için bir yarış koşulu vardır. sistem yeniden başlatılırsa ve .pid mevcutsa ancak farklı bir uygulama tarafından kullanılıyorsa, bu 'öngörülemeyen sonuçlara' yol açabilir.


0

Örneğin GNU / Linux'ta şunları kullanabilirsiniz:

Pid=$(pidof `process_name`)

if [ $Pid > 0 ]; then

   do something
else

   do something
fi 

Veya benzeri bir şey

Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN

ve bu size uygulamanın adını, yalnızca kimliği olmayan adı gösterir.


1
pidofnegatif bir PID herhangi bir anlam ifade etmediği ve öldüremeyeceğiniz için negatif bir sayı döndürmez init, bu nedenle koşulunuz mantıklı değildir (ve ayrıca, >yeniden yönlendirme yapmasını önlemek için de kaçmanız gerekir ). Boş bir sonuç olup olmadığını kontrol etmek istersiniz, ancak elbette, iyi bir araç gibi, pidofişe yarayıp yaramadığını söylemek için bir çıkış kodu ayarlar, böylece uygun çözüm if Pid=$(pidof 'process_name'); then ...ya da ( Piddaha sonra değere ihtiyacınız yoksa ) basitçeif pidof 'process_name'; then...
tripleee

@tripleee doğru pidoförnek bash nasıl testçalışır hakkında yanlış anlamalarla dolu bir örnektir . gnu.org/software/bash/manual/html_node/…
Bruno Bronosky

0

Aşağıdaki kod, işlemimin çalışıp çalışmadığını kontrol eder, öyleyse hiçbir şey yapmaz.

Amazon SQS'dan yeni iletileri yalnızca saatte bir ve yalnızca işlem çalışmıyorsa kontrol edelim.

#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
    /usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
    echo "do nothing, just smile =)"
fi
exit $?
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.