Linux:终止后台任务

220

如何在Linux中终止最后一个生成的后台任务?

示例:

doSomething
doAnotherThing
doB &
doC
doD
#kill doB
????

20
这和编程无关怎么可能?Bash编程不算是编程吗? - flybywire
7
这段话涉及到SO和SU的重叠区域,但我认为它更适合在SO上。我这样认为的标准是,如果@flybywire是在脚本中执行此操作,那么它就属于编程范畴。如果他只是想从命令行中执行它,那么我会说它属于SU。 - Bill the Lizard
12
Shell脚本编程也是一种编程。 - cletus
8个回答

316

你可以使用作业号来终止进程。当你将一个任务放到后台时,你会看到类似如下的内容:

$ ./script &
[1] 35341

[1]是工作号,可以像这样引用:

$ kill %1
$ kill %%  # Most recent background job

要查看作业号列表,请使用jobs命令。更多内容请参见man bash
引用: 在shell中有许多引用作业的方法。字符%引入了作业名称。作业号n可以表示为%n。还可以使用启动它的名称前缀或使用出现在其命令行中的子字符串来引用作业。例如,%ce表示已停止的ce作业。如果前缀匹配了多个作业,bash会报错。另一方面,使用%?ce表示任何包含字符串ce在其命令行中的作业。如果子字符串匹配了多个作业,bash也会报错。符号%%%+指的是shell对当前作业的概念,即在前台停止或在后台启动的最后一个作业。以前的作业可以使用%-引用。在有关作业的输出(例如jobs命令的输出)中,当前作业始终带有一个+标记,以前的作业带有一个-标记。单个%(没有附带的作业规范)也表示当前作业。

2
仅供参考,我认为只有在启用作业控制时才能使用此功能。虽然我认为您可以在脚本中打开它(set -m),但它是用于交互式使用的。请参见https://dev59.com/inRB5IYBdhLWcg3wNk53 - falstro
11
非常有用的符号,这些 %1%% 特别实用。有些进程无法通过 Ctrl-C 结束,你需要使用 Ctrl-Z 暂停它们,然后使用 kill -9 %% 命令强制结束它们。我发现一个很有用的例子是:while true; do mplayer <some unstable online radio>; date >> restarts.log; done - 使用 Ctrl-C 只能让代码进入下一个循环迭代。以前我不得不使用 ps 或者 jobs -l 命令查询 PID,并重新输入它,这很繁琐。 - Tomasz Gandor
所有工作都有一个吗? - CMCDragonkai
3
这就是为什么你可能想要用while sleep 1替换while true。如果你可以接受这个短暂的延迟,那么它会在重新启动之前等待一段时间。如果你按两次ctrl-c,第二次将中断睡眠,并以非零退出码结束,跳出循环。 - falstro
如果存在关于归属用户的混淆,结果可能会是 "kill: failed to parse argument: '%1'"(例如,在 sudo less /media/someUser/364c375a-523c-41ae-b858-0fa9774540a3/grub/grub.cfg 中按下 Ctrl + Z 后执行 sudo kill %1 命令)。 kill %1(不带 sudo)也可以产生所需的结果,但会显示一个错误信息: "bash: kill: (23076) - Operation not permitted.[1]+ Stopped sudo less /media/someUser/364c375a-523c-41ae-b858-0fa9774540a3/grub/grub.cfg"。 - Peter Mortensen

252
在Bash中有一个特殊的变量来处理这个问题:
kill $!

$! 会扩展为在后台执行的最后一个进程的 PID。


71
不,^Z并不是将作业放到后台运行,它会停止它们。接下来执行 bg 命令才能让作业在后台继续执行,并且此后 $! 才能正常使用。 - falstro
假设????代表在kill之后要执行一个或多个命令,如果其中任何一个命令依赖于后台进程完成的工作,请注意后台进程在接收到(可捕获的)信号后在信号处理程序中执行的任何清理或完成任务。最好在任何此类“依赖”命令的第一个命令之前添加一个wait(可能跟随一个sync甚至是一个sleep <n>)。 - ack
2
完成:由于单个%也指当前作业,因此您可以使用“kill%”杀死已停止的作业(^ z)。我几乎总是在^ z之后使用它。 - t3o
只有在启用了作业控制的情况下才能使用此功能,这仅在交互式 shell 中默认开启(尽管您提到使用 ctrl-z,我想您也是在使用交互式 shell)。但这已经在其他答案中概述过了,不知道为什么要“完整” :) - falstro

51

以下命令可以列出您会话中所有后台进程及其pid。您随后可以使用它来终止该进程。

jobs -l

使用示例:

$ sleep 300 &
$ jobs -l
[1]+ 31139 Running                 sleep 300 &
$ kill 31139

31

这将终止所有后台进程:

jobs -p | xargs kill -9

1
这是我以前使用的方法,但是kill -9 %%打字更少 :) - Tomasz Gandor
4
这将只结束当前工作,即在前台停止或在后台启动的上一个工作。答案中的命令将结束所有工作。 - Alex Bitek
5
不要使用"kill -9"命令。这个命令会强制结束进程,即使它正在执行重要任务或者资源清理。相反,尝试使用其他信号(例如SIGTERM)来优雅地终止进程,让它有机会完成必要的清理和关闭操作。这样做可以避免数据丢失或损坏等问题,并确保系统的稳定性。 - Lesmana

2
skill doB

skill 是 kill 命令的一个版本,它允许你根据给定的条件选择一个或多个进程。


0

John Kugelman的回答所述,%与工作规范有关。

我们如何高效地找到它?使用less的 &pattern 命令。似乎man使用了less分页器(我不太确定)。在'man' Bash中,键入&%,然后键入Enter。它只会显示包含“%”的行。要重新显示所有内容,请键入&。然后再次键入Enter


0
你需要它的pid...使用"ps -A"来找到它。

-4

只需使用killall命令:

killall 任务名称

要获取更多信息和更高级的选项,请键入“man killall”。


4
如果你可以轻松获取进程ID,我认为使用killall有些过于激进了。而且很危险,特别是如果你是root用户。 - Dave Vogt
3
еҰӮжһңдҪ дёҚеҫ—дёҚдҪҝз”Ёkillall pythonжҲ–иҖ…killall javaе‘Ҫд»ӨпјҢиҖҢеңЁзі»з»ҹзҡ„е…¶д»–ең°ж–№жңүдёҖдәӣжңүз”Ёзҡ„зЁӢеәҸжӯЈеңЁиҝҗиЎҢпјҢиҝҷж ·еҒҡе°ұдёҚеӨӘеҗҲйҖӮдәҶгҖӮ - Tomasz Gandor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接