![为什么有些命令会“挂起”终端直到完成为止?](https://linux22.com/image/19910/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%9C%89%E4%BA%9B%E5%91%BD%E4%BB%A4%E4%BC%9A%E2%80%9C%E6%8C%82%E8%B5%B7%E2%80%9D%E7%BB%88%E7%AB%AF%E7%9B%B4%E5%88%B0%E5%AE%8C%E6%88%90%E4%B8%BA%E6%AD%A2%EF%BC%9F.png)
有时您从终端运行程序,例如lxpanel
†。终端不会让你回到提示符,它会挂起。您可以按Ctrl+C返回提示符,但这会杀死lxpanel
.但是,按Alt+ F2(会弹出一个窗口来执行命令)并运行lxpanel
可以正常工作。
为什么是这样?从终端运行命令与按Alt+时出现的“运行”窗口运行命令有何不同F2?
†这里的 lxpanel 只是作为示例。我在多个程序中都经历过这种情况
答案1
默认情况下,终端将在前台运行该程序,因此在程序完成之前您不会返回到 shell。这对于从标准输入读取和/或写入标准输出的程序很有用——您通常不希望它们同时运行很多。如果你想让一个程序在后台运行,你可以这样启动它:
$ lxpanel &
或者,如果它已经在运行,您可以使用Ctrl+暂停它Z,然后运行bg
将其移至后台。无论哪种方式,您最终都会得到一个新的 shell 提示符,但程序仍在运行,并且其输出将出现在终端中(因此当您正在打字时它可能会突然出现)
有些程序(通常是守护进程)在启动时会分叉一个单独的进程,然后让主进程立即退出。这可以让程序继续运行而不会阻塞您的 shell
答案2
当您在终端中启动程序时,终端将“挂起”直到您的程序停止。按Ctrl+c您将关闭程序,从而返回到提示符。您将在所有 GUI 应用程序中看到这一点,例如尝试 Firefox。
当您使用其他方法(例如 Alt+F2)或单击菜单时,您的程序将在后台启动,因此不会发生任何奇怪的情况(并且无论如何也没有命令提示符)。
如果您仍然想从终端启动 GUI 应用程序,请&
在命令末尾附加,如下所示
lxpanel &
这告诉终端lxpanel
在后台运行并立即给您另一个提示。
答案3
默认情况下,程序通过在该 shell 的前台运行的 shell 运行。这会导致 shell 暂停操作并将 stdin/stdout/sterr 从终端定向到程序。通过桌面环境运行的程序是分叉的,这使它们独立于运行它们的程序运行。这可以通过在&
命令中附加 a 来在大多数 shell 中进行模拟,尽管这仍然会将 std* 连接到终端(尽管从后台程序上的 stdin 读取数据会更加复杂)。
答案4
& 背景很好,除了稍后需要控制台交互的程序(例如,“apt -y update &”最终进入停止状态,因为它想在很久以后提示用户“真的真的强制吗?”问题) ....当没有人再看的时候)。
为了堵住这个漏洞并通知进程一个终端实际上永远不会变得可用,我在我的一些命令中附加了一个 <&- ,将它们与活动终端完全分离,告诉它们 STDIN 不再可能。 如果您使用 /bin/bash,请确保它是您的 shell。 该脚本将继续记录与没有可用于投射任何提示的伪终端相关的任何错误。
例如:
`./runme.sh &> runme.log <&- & disown`
是我与当前终端会话解除关联的最终方法。 STDOUT 和 STDERR 都会记录到 runme.log,如果您的控制台或 shell 提前终止,或者您注销/su 到不同的帐户(runme 没有终端垃圾),这并不重要,并且感谢甚至不承认父子关系PID 关系被删除。
更新:即使如此,我在将信号量与原始父级的名称关联起来时遇到了麻烦,所以现在我建议:
at now <<< "(cmd1; cmd2; etc.) &> logfile.log"
当然,如果您想通过电子邮件接收 CRON 的输出,请删除 &>,或者将其全部重定向到 /dev/null 而不是文件。