如何消除从终端启动 GUI 时的烦恼?

如何消除从终端启动 GUI 时的烦恼?

我更喜欢从终端窗口启动 GUI 应用程序,而不是使用图形桌面。一个常见的烦恼是,开发人员通常没有预料到这种类型的使用,因此应用程序会向 stdout 或 stderr 打印大量无用、神秘或无信息的消息。由于使用 & 在后台运行程序,会生成作业创建和终止的报告,因此终端上会出现进一步的混乱。

对于这些问题,接受命令行参数并处理自动完成的解决方法是什么?

有关的:https://stackoverflow.com/questions/7131670/make-bash-alias-that-takes-parameter

答案1

立即将标准错误重定向到/dev/null是一个坏主意,因为它会隐藏早期的错误消息,并且故障可能难以诊断。我建议使用以下start-appzsh 脚本:

#!/usr/bin/env zsh
coproc "$@" 2>&1
quit=$(($(date +%s)+5))
nlines=0
while [[ $((nlines++)) -lt 10 ]] && read -p -t 5 line
do
  [[ $(date +%s) -ge $quit ]] && break
  printf "[%s] %s\n" "$(date +%T)" "$line"
done &

只需运行它:start-app your_command argument ...

该脚本最多输出 10 行消息,持续时间最多 5 秒。但请注意,如果应用程序立即崩溃(例如由于分段错误),您将不会看到任何错误消息。当然,您可以通过各种方式修改此脚本来执行您想要的操作......

注意:要在 zsh 中使用补全功能start-app,只需执行以下操作:

compdef _precommand start-app

在bash中:

complete -F _command start-app

(从 forexectimein中复制/usr/share/bash-completion/bash_completion)。

答案2

这个答案是针对 bash 的。作为示例,以下是我在 .bashrc 中所做的操作,以创建一个方便的命令ev来启动 PDF 查看器 Evince。

ev() { (evince "$1" 1>/dev/null 2>/dev/null &) }
complete -f -o default -X '!*.pdf' ev

第一行定义了一个函数ev。当您在命令行上使用函数时,函数的名称将被识别,如下所示:

ev foo.pdf

(这是一种与别名不同的机制,并且优先级较低。)Evince 到 stdin 和 stdout 的输出被发送到 bitbucket (/dev/null)。 & 符号将作业置于后台。将命令括在括号中会导致它在子 shell 中运行,这样它就不会打印有关后台作业创建或完成的消息。

我的 .bashrc 中的第二行使用 bash 的完整函数来告诉 bash ev 命令的参数应该是一个扩展名为 pdf 的文件。这意味着,如果我的目录中还有文件 foo.tex、foo.aux 等,我可以键入ev foo并按 Tab 键,bash 就会知道将文件名补全为 foo.pdf。

答案3

另一种可能性是使用command降级exec特别的内置到普通的旧内置,例如:

alias shh='command exec >/dev/null 2>&1'

所以现在你可以这样做:

(shh; call some process &)

我刚刚注意到这command不起作用zsh (就像在大多数其他 shell 中一样),但如果它不起作用,你可以这样做:

alias shh='eval "exec >/dev/null 2>&1"'

...这应该在任何地方都有效。

事实上,你甚至可以这样做:

alias shh='command exec >"${O:-/dev/null}" 2>&1'

所以你可以这样做:

O=./logfile; (shh;echo can anyone hear &)
O=; (shh; echo this\? &)
cat ./logfile

输出

can anyone hear

在与 @vinc17 的评论讨论之后,值得注意的是,几乎所有 GUI 应用程序的控制台输出通常都是用于Xs tty - 它的控制台。当您XX .desktop文件运行应用程序时,它生成的输出将路由到X的虚拟终端 - 这是您X最初启动的任何 tty。我可以用 来寻址这个 tty 号码$XDG_VTNR

但奇怪的是 - 也许是因为我刚刚开始使用startx- 我似乎不能再只写到/dev/tty$XDG_VTNR.这也可能(我认为可能性更大)与 v1.16中最近实现的重大更改有关,Xorg该更改允许它在用户会话下运行,systemd而不是要求特权。

不过,我可以这样做:

alias gui='command exec >/dev/tty$((1+$XDG_VTNR)) 2>&1'

(gui; some x app &)

现在所有的some x app控制台输出都被路由到/dev/tty$((1+$XDG_VTNR))而不是我xterm的 pty。我可以随时获取最后一页,例如:

fmt </dev/vcs$((1+$XDG_VTNR))

无论如何,最好的做法是专门使用一些虚拟终端来记录输出。/dev/console通常已经为此保留,尽管您可能不希望执行chown您愉快地写入该内容可能需要的操作。你可能有一些功能可以让你做一个printk- 基本上是打印/dev/console- 所以我想可以这样使用它。

做到这一点的另一种方法是专门普蒂达到这样的目的。例如,您可以保持一个xterm窗口打开,将运行时的输出保存在环境变量中,并使用该值作为的输出的tty目标。gui这样,所有日志都会被路由到一个单独的日志窗口,然后您可以根据需要滚动浏览。

我曾经写过一个答案bash如果您感兴趣的话,可以了解如何对历史做类似的事情。

相关内容