プロセス(例:myCommand)を開始してそのpidを取得したい(後で終了できるようにするため)。
名前でpsとフィルターを試しましたが、名前でプロセスを区別できません
myCommand
ps ux | awk '/<myCommand>/ {print $2}'
プロセス名は一意ではないためです。
私はプロセスを実行できます:
myCommand &
このPIDは次の方法で取得できることがわかりました。
echo $!
より簡単な解決策はありますか?
私はmyCommandを実行して、1つの行コマンドの結果としてそのPIDを取得できれば幸いです。
echo $!
よりも簡単なものは何ですか? 1行として:
myCommand & echo $!
コマンドを小さなスクリプトで囲みます
#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file
sh -c
とexec
を使用して、コマンドのPIDをbeforebeforeでも実行できます。myCommand
を開始して、そのPIDが実行を開始する前に出力されるようにするには、以下を使用できます。
sh -c 'echo $$; exec myCommand'
これは、新しいシェルを開始し、そのシェルのPIDを出力し、次にexec
ビルトインを使用して、コマンドでシェルをreplaceして、同じであることを確認しますPID。シェルがexec
組み込みコマンドを実行すると、シェルは 実際にはになるそのコマンド ではなく、 それ自体の新しいコピーをフォークするより一般的な動作 よりも、独自の個別のPIDを持ち、それがコマンドになります。
これは、非同期実行(&
を使用)、ジョブ制御、またはps
を使用した検索を含む代替方法よりもはるかに簡単であることがわかりました。これらのアプローチは問題ありませんが、それらを使用する特定の理由がない限り-たとえば、コマンドが既に実行されている場合は、そのPIDの検索またはジョブ制御の使用が理にかなっています-この方法を最初に検討することをお勧めします。 (そして、私はこれを達成するために複雑なスクリプトや他のプログラムを書くことを確かに考慮しませんでした)。
この回答 には、この手法の例が含まれています。
使用しているシェルがボーンスタイルであり、これらのセマンティクスでexec
ビルトインをサポートしている場合でも、sh -c
(または同等のもの)を使用して新しいseparateこの目的のためのシェルプロセス。
myCommand
になると、後続のコマンドの実行を待機しているシェルはなくなります。 sh -c 'echo $$; exec myCommand; foo
は、foo
に置き換えられた後、myCommand
を実行することはできません。これを最後のコマンドとして実行するスクリプトを作成しているのでない限り、他のコマンドを実行しているシェルでecho $$; exec myCommand
を使用することはできません。(echo $$; exec myCommand)
はsh -c 'echo $$; exec myCommand'
より構文的に優れている可能性がありますが、$$
_(
内で)
を実行すると、サブシェルではなく親シェルのPIDが提供されます自体。ただし、新しいコマンドのPIDになるのはサブシェルのPIDです。一部のシェルは、サブシェルのPIDを見つけるための独自の非移植可能なメカニズムを提供します。これは、これを使用できます。特に、 Bash 4 では、(echo $BASHPID; exec myCommand)
は機能します。最後に、一部のシェルは optimization を実行することに注意してください。シェルは必要ないことがわかっている場合、exec
(つまり、最初にforkを忘れる)のようにコマンドを実行します。その後は何でもします。実行する最後のコマンドであるときにいつでもこれを実行しようとするシェルもあれば、コマンドの前後に他のコマンドがない場合にのみ実行するシェルもあれば、まったく実行しないシェルもあります。その効果は、exec
を書くのを忘れてsh -c 'echo $$; myCommand'
だけを使用した場合、sometimesが正しいPIDをsomesomeシェルを備えたシステム。 そのような振る舞い に依存することはお勧めしません。代わりに、それが必要な場合は常にexec
を常に含めるようにしてください。
もっと簡単な解決策は知りませんが、$を使用していません!十分ですか?他の人が言うように、後で必要になる場合はいつでも他の変数に値を割り当てることができます。
補足として、psからパイプする代わりに、pgrep
またはpidof
を使用できます。
pidをファイルに登録した後、bashスクリプトからexecを使用します。
例:
args p1、p2、p3で実行する「forever.sh」という名前のスクリプトがあるとします。
forever.shソースコード:
#!/bin/sh
while [ 1 -lt 2 ] ; do
logger "$0 running with parameters \"$@\""
sleep 5
done
reaper.shを作成します。
#!/bin/sh
echo $$ > /var/run/$1.pid
exec "$@"
reaper.shからforever.shを実行します。
./reaper.sh ./forever.sh p1 p2 p3 p4 &
forever.shは、5秒ごとにsyslogに行を記録するだけです。
/var/run/forever.sh.pidにpidができました
cat /var/run/forever.sh.pid
5780
そして、forever.shは正常に実行されています。 syslog grep:
Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"
プロセステーブルで確認できます。
ps axuwww|grep 'forever.sh p1' |grep -v grep
root 5780 0.0 0.0 4148 624 pts/7 S 16:07 0:00 /bin/sh ./forever.sh p1 p2 p3 p4
Bashシェルでは、$!
の代わりにjobs -p
が組み込まれている場合があります。場合によっては、!
の$!
が変数展開の前(または代わり)にシェルによって解釈され、予期しない結果が生じることがあります。
たとえば、これは機能しません。
((yourcommand) & echo $! >/var/run/pidfile)
これは:
((yourcommand) & jobs -p >/var/run/pidfile)
これはちょっとハックっぽい答えで、ほとんどの人にはうまくいきません。また、これは非常に大きなセキュリティリスクとなるため、安全であり、入力が無害化されていることを確信していない限り、実行しないでください。
ここで小さなCプログラムをstart
(または必要なもの)というバイナリにコンパイルしてから、./start your-program-here arg0 arg1 arg2 ...
としてプログラムを実行します。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc >= 2)
{
printf("%lu\n", (long unsigned) getpid());
if (execvp(argv[1], &argv[1]) < 0)
{
perror(NULL);
return 127;
}
}
return 0;
}
要するに、これはPIDをstdout
に出力し、プログラムをプロセスにロードします。それでも同じPIDが必要です。
あなたは次のようなものを使うことができます:
$ myCommand ; pid=$!
または
$ myCommand && pid=$!
2つのコマンドは、;
または&&
を使用して結合できます。 2番目のケースでは、pidは最初のコマンドが成功した場合にのみ設定されます。プロセスIDは$pid
から取得できます。