71532


以下のようなシェルスクリプトtest.shがあります。

[code]

    #!/bin/bash
    for i in $(seq 10);
    do
      echo "i=$i"
      sleep 1
    done
    
[/code]

それを以下のように実行した場合、 `kill $P1` でプロセス./test.shは直ちに終了します。

[code]

    #!/bin/bash
    ./test.sh &
    P1=$!
    sleep 3
    kill $P1
    echo "end"
    
[/code]

[code]

    i=1
    i=2
    i=3
    end
    
[/code]

ただし./test.shのあとに&&で後続コマンドを設定した場合、./test.shは `kill $P1` で終了しません。

[code]

    #!/bin/bash
    ./test.sh && echo "yes" &
    P1=$!
    sleep 3
    kill $P1
    echo "end"
    
[/code]

[code]

    i=1
    i=2
    i=3
    end
    i=4
    i=5
    i=6
    i=7
    i=8
    i=9
    i=10
    
[/code]

なぜこうなるのでしょうか。  
また、最初の実行と同じように、直ちにtest.shを終了するにはどうすればいいでしょうか。


CC BY-SA 4.0
2020-10-27T01:37:52.103
71528
2020-10-27T05:47:47.627
2020-10-27T04:55:35.770
3060
28998
question
linux bash
bash: &&で実行されるコマンドリストのkill


`$!`は **最後に実行された** バックグラウンド (非同期) コマンドの プロセス ID に展開されます。  
最後に実行されたのは`./test.sh && echo "yes"`であって`./test.sh`ではないので`$P1`に入るプロセスIDも別の値です。  
なので、`P1=$(pgrep test.sh)`と変更すれば期待通りに動作すると思います。


CC BY-SA 4.0
2020-10-27T04:54:47.330
71531
2020-10-27T04:54:47.330
25936
71528
answer


> また、最初の実行と同じように、直ちにtest.shを終了するにはどうすればいいでしょうか。

伽語蓮弥の回答にあるとおり、P1には`./test.sh && echo "yes"`のPIDが格納されます。  
`./test.sh`はP1の子のプロセスなので、

[code]

    kill $P1
    
[/code]

の代わりに

[code]

    pkill -P ${P1}　＃親プロセスを指定してkill
    
[/code]

とすることにより`./test.sh`が終了します。


CC BY-SA 4.0
2020-10-27T05:47:47.627
71532
2020-10-27T05:47:47.627
35558
71528
answer