$!を使用してシェルスクリプトのPIDを取得すると、正しい(最終)PIDは提供されません。

$!を使用してシェルスクリプトのPIDを取得すると、正しい(最終)PIDは提供されません。

後で終了できるように、シェルスクリプトのPIDを取得しようとしています。

bash "home/lewis/builds/arduino/arduino-1.8.12/arduino" & disown
echo "$!"

上記は実行され、37977を返します。

しかし、

走ると手にkill 37977入る

bash: kill: (37977) - No such process

私の考えでは、スクリプトが/home/lewis/builds/arduino/arduino-1.8.12/arduino37977に加えて別のプロセスを生成するためだと思います。

シェルスクリプトや私が実行している他のコマンドの最終PIDを取得する方法はありますか?通常はうまく機能しますが、このインスタンスは問題を引き起こします。

これが再発する場合に備えて、他のコマンドに移動できるソリューションが必要です。

答え1

生成されたプロセスが別のプロセスを開始して終了する場合、新しいプロセスはすべて同じプロセスグループID(PGID)を持ち、そのIDは元のプロセスのPID(例では37977)でなければなりません。だからあなたがしたいのはPGIDのすべてのプロセスを終了する方法です。これは、kill以下に説明するように負のPIDを使用して実行できますman kill

          -n     where n is larger than 1.  All processes in process group
                 n are signaled.  When an argument of  the  form  '-n'  is
                 given,  and it is meant to denote a process group, either
                 a signal must be specified first, or the argument must be
                 preceded  by a '--' option, otherwise it will be taken as
                 the signal to send.

だからあなたが望むものは次のとおりです。

bash "home/lewis/builds/arduino/arduino-1.8.12/arduino" & disown
kill -TERM -"$!"

個々のPIDのリストを収集する必要がある場合は、次のことができます。

bash "home/lewis/builds/arduino/arduino-1.8.12/arduino" & disown
ps -eo pgid,pid | awk -v pid=$! '$1==pid{print $2}')

これにより、PGIDを含むPIDのリストが返されます$!。シェルが配列をサポートしている場合(bashはサポート)、次のこともできます。

pids=($(ps -eo pgid,pid | awk -v pid=$! '$1==pid{print $2}'))
for pid in "${pids[@]}"; do echo "Killing $pid"; kill $pid; done

または必要な他のもの。

関連情報