bashスクリプトで、次のことを(擬似コードで)実行したいと思います。
if [ a process exists with $PID ]; then
kill $PID
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
は、プロセスが実行中であり、プロセスを強制終了する権限がない場合でも、終了コードがゼロ以外になることです。例えば:
kill -0 $known_running_pid
と
kill -0 $non_running_pid
通常のユーザーには区別できないゼロ以外の終了コードがありますが、そのうちの1つは仮定による実行であり、もう1つは実行されていません。
部分的に関連し、AnrDaemonによって提供される追加情報:initプロセス(PID 1)は確かにすべてのLinuxマシンで実行されていますが、すべてのPOSIXシステムがLinuxであるとは限りません。PID1がそこに存在することは保証されていません。
kill -0 1
-bash: kill: (1) - No such process …
テストの本体が「キル」である場合、キルと競合状態を議論する答えは正確に正しいです。一般的な「 bashにPIDが存在するかどうかをどのようにテストしますか」を探しに来ました。
この/proc
方法は興味深いものですが、ある意味でコマンド抽象化の精神を壊します。つまり、Linusがファイルを別の名前で呼び出すことにした場合はどうなるので、ps
調べる必要はありません。/proc
exe
プロセスの存在を確認するには、次を使用します
kill -0 $pid
しかし、@ unwindが言ったように、いずれにせよ終了させたい場合は、
kill $pid
そうしないと、最初のの後にプロセスが消えた可能性がある競合状態になりますkill -0
。
のテキスト出力を無視しkill
て、終了コードに基づいて何かを実行したい場合は、次のことができます。
if ! kill $pid > /dev/null 2>&1; then
echo "Could not send SIGTERM to process $pid" >&2
fi
ps
のコマンド-p $PID
はこれを行うことができます:
$ ps -p 3531
PID TTY TIME CMD
3531 ? 00:03:07 emacs
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
。
最初の方法:2番目の列のPIDに対して実行ps aux
します。この例では、を探し、次にPIDを探します。grep
firefox
[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」を使用してください。
あなたが望むようです
wait $PID
終了すると戻り$pid
ます。
それ以外の場合は使用できます
ps -p $PID
kill -0 $pid
プロセスがまだ生きているかどうかを確認します(これは、pidを所有していなくても機能するためよりも効果的です)。
これは悪い解決策だと思います。それは競合状態につながる可能性があります。テストと殺害の呼びかけの間にプロセスが終了した場合はどうなりますか?その後、キルは失敗します。では、すべての場合にkillを試して、その戻り値をチェックして、それがどのように行われたかを調べてみませんか?
たとえば、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なしの名前だけが表示されます。
pidで:
pgrep [pid] >/dev/null
名前で:
pgrep -u [user] -x [name] >/dev/null
「-x」は「完全一致」を意味します。
ここでは、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が存在するが、別のアプリケーションで使用されている場合、これは「予期しない結果」を引き起こす可能性があります。
私はここで@FDSの答えから学び、賛成しました。なぜなら、それは良くて正しいからです。しかし、これが私が読みやすく理解しやすいと思うフォームです:
pid=1234
ps --pid "$pid" > /dev/null
if [ "$?" -eq 0 ]; then
echo "PID $pid exists and is running."
fi
更新:shellcheck check_if_pid_exists.sh
冗長性を回避するために(@FDSが示すように)実際には別の方法で実行する必要があることを教えてくれます:
pid=1234
if ps --pid "$pid" > /dev/null; then
echo "PID $pid exists and is running."
fi
だから...多分私は将来そのようにすることに適応するでしょう。
とにかく、ここに完全な実行可能なプログラムがあります(これが私の貢献だと思います):
check_if_pid_exists.sh:
#!/usr/bin/env bash
pid=1234
if [ "$#" -gt 0 ]; then
# At least 1 argument was passed in, so assume it is the PID
pid="$1"
fi
# Try to print the process (`ps`) information for this PID. Send it to
# /dev/null, however, so we don't actually have to look at it. We just want
# the return code, `$?`, which will be 0 if the process exists and some other
# number if not.
ps --pid "$pid" > /dev/null
if [ "$?" -eq 0 ]; then
echo "PID $pid exists and is running."
else
echo "PID $pid does NOT exist."
fi
実行呼び出しと出力のサンプル:
eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh 28876
PID 28876 exists and is running.
eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh
PID 1234 does NOT exist.
eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh 5678
PID 5678 does NOT exist.