如何在 linux 的后台停止脚本 运行?

How do I stop a scirpt running in the background in linux?

假设我有一个愚蠢的脚本:

while true;do
  touch ~/test_file
  sleep 3
done

然后我将脚本启动到后台并离开终端:

chmod u+x silly_script.sh
./silly_script.sh &
exit

我现在有办法识别并停止该脚本吗?我的看法是,每个命令都是在它自己的进程中启动的,我可能能够捕获并终止一个命令,如 'sleep 3' 但不是整个脚本的执行,我错了吗?我希望一个进程以脚本名称出现,但它没有。如果我用 'source silly_script.sh' 启动脚本,我找不到名为 'source' 的进程。我是否需要识别正在执行脚本的 bash 的实例?我该怎么做?

编辑:有一些创造性的解决方案,但到目前为止,它们需要立即存储脚本执行的 PID,或者 bash 会话不与 ^D 一起保留或 exit。我明白,这种 运行 脚本的方式应该避免,但我很难相信,任何低权限用户都可以,即使是意外地,在后台启动一个烦人的脚本,例如填充带有垃圾文件的驱动器或重复启动某些软件的新实例,甚至管理员也别无选择,只能重新启动服务器,因为一个简单的脚本甚至可以在不尝试的情况下隐藏它的标识符。

jobs 命令将显示所有 运行 后台作业。 您可以使用 kill 通过 id 终止后台作业,例如:

$ sleep 9999 &
[1] 58730
$ jobs
[1]+  Running                 sleep 9999 &
$ kill %1
[1]+  Terminated              sleep 9999
$ jobs
$

58730是后台任务的PID,1是它的任务id。在这种情况下 kill 58730 和 kill %1` 会产生相同的效果。

有关详细信息,请参阅 man bashJOB CONTROL 部分。

当您退出时,后台作业将收到终止信号并死掉(假设这就是它处理信号的方式 - 在您的简单示例中就是这样),除非您先 disown 它。

kill 将传播到 sleep 进程,该进程可能会忽略它并继续休眠。如果是这种情况,您仍然会在 ps -e 输出中看到它,但是父 pid 为 1 表示其原始父不再存在。

您可以使用 ps -o ppid= <pid> 查找进程的父级,或 pstree -ap 可视化作业层次结构并直观地找到父级。

在这里优秀的人的帮助下,我得到了我需要的答案:
的确,脚本 运行 在它自己的进程中包含每个命令,因此例如终止 sleep 3 命令不会对脚本 运行 做任何事情,而是通过命令与 sleep 3 一样,您可以通过查找父进程找到 bash 实例 运行ning 脚本: 所以在完成以上操作后,你可以运行 ps axf 以树的形式显示所有进程。然后你会发现这个部分:

  18660 ?        S      0:00 /bin/bash
  18696 ?        S      0:00  \_ sleep 3

现在您已经找到 bash 实例,即 运行ning 脚本并可以停止它:kill 18660 (当然你的PID会和我的不一样)