プロセスが(バックグラウンドで)まだ実行されていない場合に、特定のコマンドのみを実行するbashコマンドラインを作成できますか?
コマンドがすでに実行されているかどうかを確認するにはどうすればよいですか?
(したがって、次のコマンドをそれらの間に&&
を付けて追加できるため、次のコマンドは、最初のコマンドがtrueの場合にのみ実行されます)。
*:テスト、決定、発見、発見
daemontools を使用します。 svok
を使用して、サービス/デーモン/バックグラウンドプロセスが現在実行されているかどうかを確認できます。
他の方法については、以下を参照してください。
私は時々このテクニックを使いました:
$ pgrep <process name> || <process name>
pgrep
より前は、次の方法で行われていました。
$ ps -eaf | grep -q <[p]rocess name> || <process name>
[p]
を含むビットは、grep
が結果として自分自身を見つけられないようにします。
$ ps -eaf | grep -q [s]leep || sleep 10
独立して存在する同じプロセスの個別のインスタンスを持つことができるため、これはトリッキーになる可能性があります。たとえば、異なるポートでリッスンしているサーバーや、異なるユーザーとして実行されているサービスなどです。これらのインスタンスを区別するには、それぞれに一意のタグを割り当てる必要があります。タグは多くの場合ファイルですが、抽象名前空間のローカルソケット、TCPポートなど)にすることができます。一意の識別子であれば何でも可能です。タグがファイルの場合、プロセスID(pidfile)を含む通常のファイル、またはファイルがリッスンしている名前付きパイプまたはソケットなどです。理想的には、タグは、クライアントがそのプロセスに接続できるようにする通信エンドポイントです。
これらの異なる種類のタグはそれぞれ、探しているインスタンスが稼働中であるかどうかを確認する方法が異なります。たとえば、ローカルファイルソケットを使用して接続し、そのソケットでリッスンしているプロセスがない場合はプロセスを開始します。タグがpidfileの場合、そのプロセスIDのプロセスがあるかどうかを確認します。ただし、プロセスが停止した場合、そのIDを再利用した無関係のプロセスが存在する可能性があるため、これは壊れやすいので注意してください。 2つのクライアントが短い時間内にプロセスに到達しようとすると、プロセスが存在しないことに気づき、両方が開始しようとする場合があることに注意してください。この競合状態から適切に保護するのは難しい場合があります。
インスタンスがすべて同じスーパーバイザプロセスによって開始されている場合、インスタンスを管理する方が簡単であり、そのスーパーバイザプロセスは、インスタンスがいつ停止し、それに応じて反応するかを検出します。 多くのサービス監視プログラム これを行うことができます。
プログラムが既知の通信エンドポイントで応答せず、スーパーバイザープログラムによって管理されていない場合、貧しい人のタグはpidfile:プロセスIDを含むファイルです。プロセスを開始したら、事前に決められた名前でファイルにpidを書き込みます。プロセスが存在する必要がある場合は、pidfileを読み取り、そのpidを持つプロセスがあるかどうかを確認します。プロセスを強制終了したら、pidfileを消去します。監視なしのpidfileの最も顕著な問題は、プロセスが停止した場合、そのpidが無関係なプロセスによって再利用される可能性があることです。少なくともプロセス名またはプロセス実行可能ファイルをチェックして、正しいプロセスと通信していることを確認する必要があります。多くのUNIXバリアントには pgrep コマンドがあります:pgrep SOMENAME
は、名前にSOMENAMEがサブストリングとして含まれるプロセスをリストします。特定のユーザーに制限したり、完全一致を要求したり、「プロセス名」の考えられる概念のどれを使用するかを変更したりするための追加オプションがあります。
このアプローチを使用できます:
if [[ -z $(ps -C appname -opid=) ]]; then
appname && secondapp
fi
別のオプション:
pgrep -xq processname
ps -eo comm= | sed 's|.*/||' | grep -xq processname
sed 's|.*/||'
は、OS Xのdirname部分を削除しますGNU/Linuxでは、ps -o comm
はコマンド名を15文字に切り捨て、pgrep
とps -C
は最初の15文字のみに一致します。
ps -C
(コマンド名の一致)は、OS Xではサポートされていません。
OS Xでは、ps -o comm
はコマンドの絶対パスを出力し、ps -co comm
はコマンド名のみを出力します。 GNU ps -o comm
はコマンド名のみを出力し、-c
は異なる意味を持ちます。
OS Xのpgrepには、-a
がない祖先プロセス(bash、Terminal、またはlaunchdなど)は含まれていません。 GNUのpgrepはデフォルトでそれらを含み、-a
をサポートしていません。
grep -x
およびpgrep -x
は-F
を意味しないため、プロセス名に正規表現文字を含めることができる場合は-Fx
を使用してください。
申し訳ありませんが、同じコマンドラインが「ps」の結果に2回表示されるため、これらのソリューションはすべてcontabをサポートしていません。
これが私のものです:
## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
echo "WARNING : le process $pid tourne deja : $0"
ps -edf | grep `basename $0` | grep -v grep
echo "WARNING : Arrêt de cette instance ($$)."
exit 7
fi
echo $$ >$lock_file
バッシュと
#!/usr/bin/env bash
[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name> <Command here>"; exit 1; }
ifnotrun(){
local p=$1
if ! ps -C "$1" -opid=
then
cmd=($@)
echo ${cmd[@]:1}
else
echo "Process \"$p\" Already Running.."
exit 1
fi
}
ifnotrun $*
注:-出力に問題がなければ、echo
を削除します。
コマンドをbeckgreoudで実行する場合について説明します。 「$!」最後のバックグラウンドプロセスのPIDを保存します。したがって、これを使用して、上記の回答に続くプロセステーブルでそれを見つけることができます。
sleep 4 &
ps -ef | grep -w $! ...
組み込みコマンド「ジョブ」-これを試してください:
sleep 4&
J=`jobs`
while [ "$J" ]; do
sleep 1
jobs # This line flush the jobs' bufer.
J=`jobs`
done
"&&"オプションについて
&&の代わりに、コマンドwaitを使用します。次の例では、myproc1が終了するまでmyproc2は実行されません。
myproc1 &
wait
myproc2
プロセスの状態を取得します。
ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'
参照:
D uninterruptible sleep (usually IO)
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped, either by a job control signal or because it is being traced
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
たとえば、これを使用して、tmuxセッションでsoxプロセスを条件付きで再生または一時停止しました。
/usr/local/bin/tmux if-Shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
'send -t sox "fg" Enter' \
'send -t sox C-z'