web-dev-qa-db-ja.com

プロセスID(PID)が存在するかどうかを確認する方法

Bashスクリプトでは、次のことを(擬似コードで)行いたいと思います。

if [ a process exists with $PID ]; then

    kill $PID 

fi

条件文の適切な式は何ですか?

161
Richard H

プロセスの存在を確認するには、次を使用します

kill -0 $pid

しかし、@ unwindが言ったように、とにかくそれを殺すつもりなら、

kill $pid

または、競合状態になります。

killのテキスト出力を無視し、終了コードに基づいて何かをしたい場合は、次のことができます。

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

最善の方法は次のとおりです。

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

の問題:

kill -0 $PID

pidが実行されていて、それを強制終了する権限がない場合でも、終了コードはゼロ以外になります。例えば:

kill -0 1

そして

kill -0 $non-running-pid

通常のユーザーには区別できない(ゼロ以外の)終了コードがありますが、initプロセス(PID 1)は確実に実行されています。

討論

テストの本体が「キル」である場合、キルおよび競合状態を議論する答えは正確に正しいです。一般的な「bashでPIDの存在をどのようにテストしますか」を探しに来ました。

/ procメソッドは興味深いものですが、ある意味で「ps」コマンドの抽象化の精神を壊します。

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

または

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

後者の形式では、-o pid=は、ヘッダーなしでプロセスID列のみを表示する出力形式です。引用符は、空でない文字列演算子-nが有効な結果を得るために 必要 です。

58
user2683246

-p $PIDを指定したpsコマンドでこれを行うことができます。

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

次の2つの方法があります。

私のラップトップで特定のアプリケーションを探すことから始めましょう:

[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

すべての例でPID 3358が検索されます。

最初の方法:「ps aux」を実行し、2列目のPIDに対してgrepを実行します。この例では、firefoxを探し、次にPIDを探します。

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

したがって、コードは次のようになります。

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

2番目の方法/proc/$PIDディレクトリで何かを探すだけです。この例では「exe」を使用していますが、他のものを使用できます。

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

したがって、コードは次のようになります。

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

ところで:kill -9 $PID || trueの何が問題なのですか?


編集:

数ヶ月間それについて考えた後..(約24 ...)ここで私が与えた最初のアイデアはニースのハックですが、非常に移植性がありません。 Linuxのいくつかの実装の詳細を教えていますが、Mac、Solaris、または* BSDでは動作しません。将来のLinuxカーネルでも失敗する可能性があります。他の応答で説明されているように、「ps」を使用してください。

11
elcuco

それは悪い解決策だと思います。それは競合状態に開かれます。テストと強制終了の間にプロセスが停止した場合はどうなりますか?その後、killは失敗します。それでは、すべての場合に強制終了を試みて、その戻り値を確認して、それがどのように行われたかを確認してみませんか?

8
unwind

欲しいみたい

wait $PID

$pidが終了すると戻ります。

それ以外の場合は使用できます

ps -p $PID

プロセスがまだ生きているかどうかを確認します(pidを所有していなくても機能するため、これはkill -0 $pidよりも効果的です)。

5
Gagan Gami

たとえば、GNU/Linuxでは次を使用できます。

Pid=$(pidof `process_name`)

if [ $Pid > 0 ]; then

   do something
else

   do something
fi 

または何かのような

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

そして、それはあなたにアプリの名前、IDなしの名前だけを表示します。

0
inukaze

以下のコードは、プロセスが実行されているかどうかを確認し、実行されている場合は何もしません。

プロセスが実行されていない場合にのみ、1時間ごとにAmazon SQSからの新しいメッセージをチェックしましょう。

#!/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 $?
0
Brian Sanchez

ここでは、PIDを.pid(/ run/...のようなもの)というファイルに保存し、まだ実行されていない場合にのみスクリプトを実行します。

#!/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

注: pidの呼び出し方法をチェックしないため、競合状態があります。システムがリブートされ、.pidは存在するが別のア​​プリケーションで使用されている場合、「予期しない結果」が生じる可能性があります。

0
invalidmagic