Linux

無法使用 bash 腳本終止已停止的作業

  • October 13, 2021
for i in $( seq 1 $1 )
do
       kill %$i
done

我嘗試使用此腳本終止已停止的作業,但有趣的是,即使我有作業打開,它也無法執行。

$ jobs
[10]   Stopped                 vim detect_thread.py
[11]   Stopped                 python3 detect.py
[12]-  Stopped                 python3 detect.py
[13]+  Stopped                 python3 detect.py
$ kill 13
bash: kill: (13) - No such process
$ ./delete.sh 13
./delete.sh: line 8: kill: %1: no such job
./delete.sh: line 8: kill: %2: no such job
./delete.sh: line 8: kill: %3: no such job
./delete.sh: line 8: kill: %4: no such job
./delete.sh: line 8: kill: %5: no such job
./delete.sh: line 8: kill: %6: no such job
./delete.sh: line 8: kill: %7: no such job
./delete.sh: line 8: kill: %8: no such job
./delete.sh: line 8: kill: %9: no such job
./delete.sh: line 8: kill: %10: no such job
./delete.sh: line 8: kill: %11: no such job
./delete.sh: line 8: kill: %12: no such job
./delete.sh: line 8: kill: %13: no such job

kill內置僅辨識在目前 shell 中執行的作業的格式%N。但是,shell 腳本在它們自己單獨的子 shell 中執行,並且在該子 shell 中,沒有要殺死的作業。舉個例子可能會更清楚:

$ for i in {1..5}; do sleep 100 & done
[1] 2259152
[2] 2259153
[3] 2259154
[4] 2259155
[5] 2259156
$ for i in {1..5}; do kill %$i; done
[1]   Terminated              sleep 100
[2]   Terminated              sleep 100
[3]   Terminated              sleep 100
[4]-  Terminated              sleep 100
[5]+  Terminated              sleep 100

如您所見,如果您在同一個 shell 會話中執行兩組命令,這將按預期工作。同樣,如果您從同一個 shell 腳本啟動並終止命令,它也可以工作:

#! /usr/bin/env bash
for i in {1..5}; do
 sleep 100 &
done

## Show the running jobs
runningSleepJobs=$(pgrep -c sleep)
echo "There are $runningSleepJobs sleep jobs running!"

for i in {1..5}; do
 kill %$i;
done
## Show that they've been stopped
runningSleepJobs=$(pgrep -c sleep)
echo "Now there are $runningSleepJobs sleep jobs running!"

如果我現在執行這個腳本,我可以看到它同時啟動,然後按預期終止作業:

$ foo.sh
There are 5 sleep jobs running!
Now there are 0 sleep jobs running!

然而,有一種方法可以解決這個問題。您可以不執行腳本,而是獲取它以便它在目前 shell 中執行:

$ cat ~/bin/foo.sh
#! /usr/bin/env bash
for i in $( seq 1 $1 )
do
       kill %$i
done

$ for i in {1..5}; do sleep 100 & done
[1] 2295221
[2] 2295222
[3] 2295223
[4] 2295224
[5] 2295225

$ jobs
[1]   Running                 sleep 100 &
[2]   Running                 sleep 100 &
[3]   Running                 sleep 100 &
[4]-  Running                 sleep 100 &
[5]+  Running                 sleep 100 &

$ . ~/scripts/foo.sh 5
[1]   Terminated              sleep 100
[2]   Terminated              sleep 100
[3]   Terminated              sleep 100
[4]-  Terminated              sleep 100
[5]+  Terminated              sleep 100

引用自:https://unix.stackexchange.com/questions/646834