有问题的应用程序是 DaVinci Resolve。我从终端启动它。当我关闭它时,来自应用程序的消息“Socket Disconnected”被写入终端输出。然后 bash 提示符正常显示。我开始输入新命令,突然在终端“Socket Disconnected”中出现另一条消息。这会干扰我所做的输入。它看起来像这样:
[andrew@unihost ~]$ davinci-resolve
... # Now I exit the application.
Host 'Fusion' Removed
FusionScript Server [37457] Terminated
Socket disconnected
[andrew@unihost ~]$ ls ls Socket disconnected
wtf!!!^C
[andrew@unihost ~]$
视频演示:https ://youtu.be/arcCOjrN7kw
为什么会发生这种情况,有没有办法防止这种情况发生?
我的猜测是主进程有一个子进程,即使在主进程死后它仍然活着。我找到了这个答案。是开发商的错吗?我可以以某种方式解决这个问题(对于子进程可能是 nohup)?
初步说明
我根本没有测试
davinci-resolve
过。这个答案被设计为通用的。分析
davinci-resolve
您的 shell在将自身放回前台并打印提示之前等待退出。davinci-resolve
显然,在主进程退出并且外壳做出反应后,主进程的某些子进程(或进一步的后代)会打印出不需要的消息。解决方案
解决方案可能很简单:
诀窍是
cat
在所有写入管道的进程都关闭它们的管道末端之前不会退出。麻烦的孩子可能从 main 继承了 stdoutdavinci-resolve
,所以cat
会等待它。通常,即使不需要的消息被打印到 stderr 或/dev/tty
(即它绕过我们的cat
),这也会起作用。重要的是孩子保持管道打开,即使它正在打印到其他地方。有以下缺点:
整个管道的退出状态将来自于
cat
,而不是来自于davinci-resolve
。在某些 shell 中,您可以对它做一些事情。来自(及其后代)的 stdout 和 stderr
davinci-resolve
将失去同步,因为前者通过cat
而后者不通过。如果你Ctrl+c那么你将杀死
cat
,可能在其他进程完成打印之前,所以你可能会错过一些你确实想看到的输出。此外,如果麻烦的消息被打印到 stderr,那么无论如何它都会被打印出来,可能是在你看到提示之后。但是,您可以对+
cat
免疫:Ctrlc麻烦的过程可能会提前关闭或重定向其标准输出,但仍会打印到标准错误。在这种情况下
cat
不会等待它。麻烦的进程可能被设计为保留,不需要的消息并不意味着进程退出。如果这个过程仍然存在并保持管道打开,那么我们的
cat
意志就会存在;你显然不想要这个。似乎不太可能有任何davinci-resolve
遗骸的后代(除非有错误),但总的来说它可能会发生。由于其中一些原因,您可能希望通过 stdout和stderr传递
cat
. 免疫+仍然是一个好主意cat
:Ctrlc现在请注意,您无法将 stderr
davinci-resolve
(及其后代)与 stdout 区分开来,它们都经过 viacat
及其 stdout。这应该不是问题,因为无论如何您都希望它们在终端中混合。如果您想单独重定向或捕获它们,那么您应该放弃我们的装置并从头开始。这可能是麻烦的过程提前关闭或重定向其stdout和stderr,并将不需要的消息直接打印到
/dev/tty
(示例)。在这种情况下,我们cat
无能为力。外壳函数
您可以将我们的解决方案实现为 shell 函数:
该函数支持将参数传递给
davinci-resolve
,但其退出状态来自cat
,而不是来自davinci-resolve
进程(如果有问题,请参阅已经给出的链接以获取想法)。后台进程实际上并没有干扰你的 shell,它只是在你的屏幕上乱涂乱画,后台进程和 shell 的输出正在混合。
有几种方法可以解决这个问题:
nohup
或文件重定向之类的东西从终端中删除消息,可能会将它们保存到文件中。ps -t
(以显示当前终端上正在运行的内容)并杀死它们。您可以键入 control-l 以清除屏幕。这将清除“Socket disconnected”消息,但会保持您的命令提示符和部分写入的命令完好无损。不幸的是,它还会清除 davinci-resolve 的输出,这对于您正在尝试做的事情可能合适,也可能不合适。
如果在主进程退出后“Socket disconnected”消息很快出现,您可以添加
; sleep 2
到您的命令并将其放在 shell 别名中。这基本上是一种提醒自己不要立即输入新命令的方法。为此,添加到你的 .bashrc