如何防止子进程干扰bash提示?

如何防止子进程干扰bash提示?

相关应用程序是 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 和 stderrdavinci-resolve将失去同步,因为前者通过cat而后者不通过。

  • 如果您Ctrl+c那么您可能会在其他进程完成打印之前杀死cat,因此您可能会错过一些您确实想看到的输出。此外,如果麻烦的消息被打印到 stderr,那么它无论如何都会被打印,可能是在您看到提示之后。

    你可以让+cat免疫:Ctrlc

    davinci-resolve | sh -c 'trap "" INT; exec cat'
    
  • 麻烦的进程可能会提前关闭或重定向其标准输出,但仍然打印到标准错误。在这种情况下cat不会等待它。

  • 麻烦的进程可能被设计为保留,并且不需要的消息并不意味着进程退出。如果这个过程仍然存在并保持管道畅通,那么我们的cat意志就会继续存在;你显然不想要这个。似乎不太可能有任何后代davinci-resolve留下(除非有错误),但一般来说它可能会发生。

出于某些原因,你可能希望传递 stdout标准错误通过cat.免疫cat+仍然是一个好主意Ctrlc

  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(以显示当前终端上正在运行的内容)找到它们并杀死它们。

相关内容