如何停止 Linux 后台运行的脚本?
假设我有一个愚蠢的脚本:
while true;do
touch ~/test_file
sleep 3
done
我将脚本启动到后台并离开终端:
chmod u+x silly_script.sh
./silly_script.sh &
exit
我现在有办法识别并停止该脚本吗?我的看法是,每个命令都是在它自己的进程中启动的,我也许能够捕获并杀死一个命令,例如“sleep 3”,但不能捕获整个脚本的执行,我错了吗?我预计会出现一个带有脚本名称的进程,但事实并非如此。如果我用“sourcesilly_script.sh”启动脚本,我找不到名为“source”的进程。我是否需要识别正在执行脚本的 bash 实例?我该怎么做呢?
编辑:已经有一些创造性的解决方案,但到目前为止,它们要求立即存储脚本执行的 PID,或者 bash 会话不保留 ^D
或 exit
。我知道,也许应该避免这种运行脚本的方式,但我发现很难相信,任何低权限用户都可以(即使是偶然)在后台启动一个烦人的脚本,例如用垃圾填充驱动器文件或重复启动某些软件的新实例,甚至管理员也没有其他选择,只能重新启动服务器,因为一个简单的脚本可以隐藏其标识符,甚至无需尝试。
Let's say I have a silly script:
while true;do
touch ~/test_file
sleep 3
done
And I start the script into the background and leave the terminal:
chmod u+x silly_script.sh
./silly_script.sh &
exit
Is there a way for me to identify and stop that script now? The way I see it is, that every command is started in it's own process and I might be able to catch and kill one command like the 'sleep 3' but not the execution of the entire script, am I mistaken? I expected a process to appear with the scripts name, but it does not. If I start the script with 'source silly_script.sh' I can't find a process by the name of 'source'. Do I need to identify the instance of bash, that is executing the script? How would I do that?
EDIT: There have been a few creative solutions, but so far they require the PID of the script execution to be stored right away, or the bash session to not be left with ^D
or exit
. I understand, that this way of running scripts should maybe be avoided, but I find it hard to believe, that any low privilege user could, even by accident, start an annoying script into the background, that is for instance filling the drive with garbage files or repeatedly starting new instances of some software and even the admin has no other option, than to restart the server, because a simple script can hide it's identifier without even trying.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这里优秀人士的帮助下,我得到了我需要的答案:
确实,脚本在其自己的进程中运行每个命令,因此例如杀死
sleep 3
命令不会对正在运行的脚本执行任何操作,而是通过像这样的命令sleep 3
您可以通过查找父进程来找到运行脚本的 bash 实例:所以完成上述操作后,您可以运行
ps axf
以树形形式显示所有进程。然后您将找到此部分:现在您已找到正在运行脚本的 bash 实例并且可以停止它:
kill 18660
(当然你的PID会和我的不同)
With the help of the fine people here I was able to derive the answer I needed:
It is true, that the script runs every command in it's own process, so for instance killing the
sleep 3
command won't do anything to the script being run, but through a command like thesleep 3
you can find the bash instance running the script, by looking for the parent process:So after doing the above, you can run
ps axf
to show all processes in a tree form. You will then find this section:Now you have found the bash instance, that is running the script and can stop it:
kill 18660
(Of course your PID will be different from mine)
jobs
命令将显示所有正在运行的后台作业。您可以使用kill通过id杀死后台作业,例如:
58730
是后台任务的PID,1
是它的任务id。在这种情况下,kill 58730
和kill %1`将具有相同的效果。有关详细信息,请参阅
man bash
的JOB CONTROL
部分。当您退出时,后台作业将收到终止信号并终止(假设这就是它处理信号的方式 - 在您的简单示例中就是如此),除非您首先
否认
它。该终止将传播到睡眠进程,该进程很可能会忽略它并继续睡眠。如果是这种情况,您仍然会在
ps -e
输出中看到它,但父级 pid 为 1,表明其原始父级不再存在。您可以使用
ps -o ppid=
查找进程的父进程,或使用pstree -ap
可视化作业层次结构并直观地查找父进程。The
jobs
command will show you all running background jobs.You can kill background jobs by id using kill, e.g.:
58730
is the PID of the backgrounded task, and1
is the task id of it. In this casekill 58730
and kill %1` would have the same effect.See the
JOB CONTROL
section ofman bash
for more info.When you exit, the backgrounded job will get a kill signal and die (assuming that's how it handles the signal - in your simple example it is), unless you
disown
it first.That kill will propogate to the
sleep
process, which may well ignore it and continue sleeping. If this is the case you'll still see it inps -e
output, but with a parent pid of 1 indicating its original parent no longer exists.You can use
ps -o ppid= <pid>
to find the parent of a process, orpstree -ap
to visualise the job hierarchy and find the parent visually.