我启动了一个 while 循环,如下所示:
while true; do {command}; sleep 180; done &
请注意&
。
我以为当我关闭终端时,这个 while 循环就会停止。但它仍在继续。自从我关闭终端会话以来已经过去了几个小时。
我如何停止这个 while 循环?
答案1
我已开始
while true; do yad; sleep 60; done &
并关闭终端进行测试,现在我遇到了同样的问题。
如果你已经关闭了终端,你已经开始循环
让我们来概览一下正在运行的进程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)
您可以看到yad
的子进程/bin/bash
,如果我关闭它, 的输出yad
将变为。如果树视图太混乱,您还可以按如下方式搜索输出1:sleep 60
ps
ps fjx | grep "[y]ad" # or respectively
ps fjx | grep "[s]leep 60"
输出行以两个数字开头,第一个是 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
这就是bash
我们要杀死的子 shell,我们刚刚找到了它的 PID,所以现在剩下的就是简单的
kill 9411 # replace 9411 with the PID you found out!
并且令人厌烦的子外壳已经永远消失。
1:用 而不是 来表示grep "[y]ad"
只是grep yad
阻止grep
进程本身出现在结果列表中。
如果你的终端还打开
bash
提供变量$!
,该变量“扩展为最近放入后台的作业的进程 ID”,因此以下操作只会终止后台中的最新进程:
kill $!
如果它是不是最新进程,只需使用内置命令即可获取正在运行的作业列表jobs
,示例输出:
[1]- Running while true; do
yad; sleep 60;
done &
[2]+ Stopped sleep 10
作业列表中有两个作业,要终止其中一个,您可以使用作业编号或快捷方式访问它%
,%+
(“当前作业”)和%-
(“上一个作业”),例如,要终止在后台运行的循环,您可以这样做
kill %1 # or
kill %-
并终止暂停的sleep 10
作业:
kill %2 # or
kill %+ # or
kill %
答案2
我需要注意的是,当你关闭输入该命令的终端时,子命令应该会随之消失。尝试重现此情况时,出现了这种行为。
现在,假设您确实处于没有发生这种情况的情况,那么终止由&
命令末尾导致的在后台运行的程序的一种方法如下:
- 打开一个新的 shell 并运行
echo $$
以记下您当前的 PID(进程 ID),这样您就不会终止自己的会话。 - 识别您认为仍在运行的程序的 PID;您可以使用命令
ps -ef | grep $SHELL
来查找哪些程序正在运行 shell。 - 注意左边第二列,并记下数值不同从
echo $$
上面的结果可以看出,这是您想要终止的 PID。 - 运行
kill -SIGTERM <pid>
命令,其中<pid>
是您在步骤#3中确定的数值 - 重复步骤 #2,确认程序不再运行
您也可以重新启动会话或计算机,但是上述方法可以让您避免这种情况。
答案3
这&
将使终端创建一个新进程并让您的代码在其中运行。因此,您的代码将独立于终端进程。即使您关闭终端,运行代码的新进程也不会停止。因此,请删除&
或执行ps -aux
,找到您的进程并终止它kill (process id)
。