相关应用程序是 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 )?
答案1
初步说明
davinci-resolve
我根本没有测试过。这个答案被设计为通用的。
分析
您的 shell 会等待davinci-resolve
退出,然后再将自己放回前台并打印提示符。显然,davinci-resolve
在主进程退出并且 shell 做出反应后,主进程的某些子进程(或更进一步的后代)会打印不需要的消息。
解决方案
解决方案可能很简单:
davinci-resolve | cat
诀窍是cat
直到写入管道的所有进程都关闭其管道末端后才会退出。麻烦的孩子可能从 main 继承了 stdout davinci-resolve
,所以cat
会等待它。通常,即使不需要的消息被打印到 stderr 或/dev/tty
(即它绕过我们的cat
),这也会起作用。重要的是孩子保持管道打开,即使它正在打印到其他地方。
也有缺点:
整个管道的退出状态将来自
cat
,而不是来自davinci-resolve
。在某些 shell 中你可以做一些事情。来自(及其后代)的 stdout 和 stderr
davinci-resolve
将失去同步,因为前者通过cat
而后者不通过。如果您Ctrl+c那么您可能会在其他进程完成打印之前杀死
cat
,因此您可能会错过一些您确实想看到的输出。此外,如果麻烦的消息被打印到 stderr,那么它无论如何都会被打印,可能是在您看到提示之后。你可以让+
cat
免疫:Ctrlcdavinci-resolve | sh -c 'trap "" INT; exec cat'
麻烦的进程可能会提前关闭或重定向其标准输出,但仍然打印到标准错误。在这种情况下
cat
不会等待它。麻烦的进程可能被设计为保留,并且不需要的消息并不意味着进程退出。如果这个过程仍然存在并保持管道畅通,那么我们的
cat
意志就会继续存在;你显然不想要这个。似乎不太可能有任何后代davinci-resolve
留下(除非有错误),但一般来说它可能会发生。
出于某些原因,你可能希望传递 stdout和标准错误通过cat
.免疫cat
+仍然是一个好主意Ctrl:c
davinci-resolve 2>&1 | sh -c 'trap "" INT; exec cat'
请注意,现在您无法区分 stderr of davinci-resolve
(及其后代)和 stdout,它们都通过cat
及其 stdout。这应该不是问题,因为无论如何你都希望它们在终端中混合。如果您想单独重定向或捕获它们,那么您应该放弃我们的装置并从头开始。
可能是麻烦的进程提前关闭或重定向其 stdout 和 stderr,并将不需要的消息直接打印到/dev/tty
(例子)。在这种情况下我们cat
无能为力。
外壳函数
您可以将我们的解决方案实现为 shell 函数:
davinci-resolve() {
command davinci-resolve "$@" 2>&1 | sh -c 'trap "" INT; exec cat'
}
该函数支持将参数传递给davinci-resolve
,但其退出状态来自cat
,而不是来自davinci-resolve
进程(如果有问题,请参阅已经给了链接的想法)。
答案2
您可以键入 control-l 来清除屏幕。这将清除“套接字已断开连接”消息,但会保持命令提示符和部分写入的命令完好无损。不幸的是,它还会清除 davinci-resolve 的输出,这可能适合也可能不适合您想要做的事情。
答案3
如果主进程退出后很快就出现“套接字已断开”消息,您可以添加; sleep 2
到命令中并将其放入 shell 别名中。这基本上是一种提醒自己不要立即输入新命令的方法。为此,请添加
alias davinci-resolve="davinci-resolve; sleep 2"
到你的.bashrc
答案4
后台进程实际上并没有干扰您的 shell,它只是在屏幕上乱写乱画,并且后台进程和 shell 的输出正在混合。
有几种方法可以解决这个问题:
- 您可以使用类似
nohup
文件重定向的方法从终端中删除消息,也可以将它们保存到文件中。 - 您可以忽略这些乱七八糟的内容,继续输入,或者如果您没有输入任何内容,只需按回车键即可获得新的提示。
- 您可以阅读后台进程发送的消息,然后使用命令行编辑击键刷新您键入的内容并使其再次可读。在普通终端模式下,Ctrl-R将执行此操作。在许多其他应用程序(如 bash)中,Ctrl-L将清除屏幕并重新打印提示符和您键入的内容。
- 您可以在专用窗口中运行该应用程序,并使用图形窗口系统的功能来打开另一个不受其输出污染的窗口。 :)(我在旁边留了一个小窗口只是为了运行如此嘈杂的应用程序。)
- 如果这种情况发生在您结束应用程序之后,并且它留下了您想要停止的工作线程,您可以使用
ps -t
(以显示当前终端上正在运行的内容)找到它们并杀死它们。