如何在后台运行循环时停止 bash?

Saq*_*Ali 33 command-line bash process job-control

我开始了一个while循环,如下所示:

while true; do {command}; sleep 180; done &
Run Code Online (Sandbox Code Playgroud)

请注意&.

我以为当我杀死终端时,这个 while 循环就会停止。但它仍在继续。自从我终止终端会话以来已经有几个小时了。

我如何停止这个 while 循环?

des*_*ert 48

我已开始

while true; do yad; sleep 60; done &
Run Code Online (Sandbox Code Playgroud)

并关闭终端进行测试,现在我遇到了同样的问题。

如果您已经关闭了终端,那么您已经开始了循环

让我们大致了解一下正在运行的进程ps fjx,我机器上的最后几行读取

 2226 11606 11606 19337 ?           -1 S     1000   0:00  \_ /bin/bash
11606 22485 11606 19337 ?           -1 S     1000   0:00  |   \_ sleep 10
 2226  9411  9411  8383 ?           -1 S     1000   0:00  \_ /bin/bash
 9411 17674  9411  8383 ?           -1 Sl    1000   0:00      \_ yad
    1  2215  2215  2215 ?           -1 Ss    1000   0:00 /lib/systemd/systemd --user
 2215  2216  2215  2215 ?           -1 S     1000   0:00  \_ (sd-pam)
Run Code Online (Sandbox Code Playgroud)

您可以将其yad视为 的子进程/bin/bash,如果我关闭yad它,它会sleep 60ps. 如果树视图太混乱,您还可以按如下方式搜索输出1

ps fjx | grep "[y]ad"  # or respectively
ps fjx | grep "[s]leep 60"
Run Code Online (Sandbox Code Playgroud)

输出行以两个数字开头,第一个是 PPID,父进程的进程 ID,第二个是 PID,进程本身的 ID。这是因为它9411出现在此处的两行中:

2226  9411  9411  8383 ?           -1 S     1000   0:00  \_ /bin/bash
9411 17674  9411  8383 ?           -1 Sl    1000   0:00      \_ yad
Run Code Online (Sandbox Code Playgroud)

那就是bash我们想要杀死的子shell,我们刚刚找到了它的PID,所以现在剩下的一切都是一个简单的

kill 9411  # replace 9411 with the PID you found out!
Run Code Online (Sandbox Code Playgroud)

烦人的子外壳已经一去不复返了。

1:符号 asgrep "[y]ad"而不是简单地grep yad阻止grep进程本身显示在结果列表中。


如果您的终端仍然打开

bash提供变量$!,它“扩展到最近放入后台的作业的进程 ID”,因此以下只是在后台杀死最新进程:

kill $!
Run Code Online (Sandbox Code Playgroud)

如果它不是最新进程,则可以使用jobs内置命令获取正在运行的作业列表,示例输出:

[1]-  Running                 while true; do
    yad; sleep 60;
done &
[2]+  Stopped                 sleep 10
Run Code Online (Sandbox Code Playgroud)

工作列表中有两个工作,要杀死其中一个,您可以使用工作编号或快捷方式访问它%%+(“当前工作”)和%-(“上一个工作”),例如,杀死在后台运行的循环可以做

kill %1  # or
kill %-
Run Code Online (Sandbox Code Playgroud)

并杀死暂停的sleep 10工作:

kill %2  # or
kill %+  # or
kill %
Run Code Online (Sandbox Code Playgroud)


cod*_*edd 5

我需要注意的是,当您关闭输入该命令的终端时,子命令应该随之消失。试图重现这显示了这种行为。

现在,假设您确实处于没有发生这种情况的情况,一种杀死您在后台运行的程序的方法,这是由&命令末尾引起的,如下所示:

  1. 打开一个新的 shell 并运行echo $$以记录您当前的 PID(进程 ID),这样您就不会终止自己的会话。
  2. 确定您认为仍在运行的程序的 PID;您可以使用该ps -ef | grep $SHELL命令来查找哪些程序正在运行 shell。
  3. 注意从左侧第二列并注意数值,不同echo $$结果上方; 这是您要杀死的PID。
  4. 运行kill -SIGTERM <pid>命令,<pid>您在第 3 步中确定的数值在哪里
  5. 重复第 2 步,确认程序不再运行

您也可以重新启动会话或计算机,但上述方法可以避免这种情况。

  • 您也可以通过按“k”,然后输入 PID,然后按两次 Enter 来使用“top”来终止进程。 (2认同)