如何阻止gedit(和其他程序)在终端输出GTK警告等?

从raring升级后,我正在运行可靠的窗口管理器。 我的桌面环境故意没有运行所有Gnome / Freedesktop守护进程 – 我不想要它们。

当我从这样的终端执行gedit

 gedit file 

每当我点击进入或保存或在其他各种场合时,它都会在我的终端上输出这样的信息:

 (gedit:5700): Gtk-WARNING **: Calling Inhibit failed: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.SessionManager was not provided by any .service files 

我理解这个警告的含义,我已经决定对我没用。

我怎么能关掉这种警告? 通过“关闭”,我不是指任何这些或类似的解决方法:

  • 将gedit的输出传递到/dev/null
  • 编写一个包装脚本,将gedit的输出传递给/dev/null
  • 创建一个别名,将gedit的输出传递到/dev/null

这些变通方法是不可接受的,因为它们必须单独应用于每个Gnome应用程序 – gedit并不是唯一一个喜欢弄乱终端的人。

首先,我还发现这些警告显示在一个开箱即用的Ubuntu上,并且没有“正确”的方法来禁用它们,我发现它很烦人(似乎最常见的“解决方案”是安装gir1.2-gtksource-3.0似乎没有工作,因为它已经安装,或者忽略它们 – 但我想完全压制它们,因为它们只是让我的终端嘈杂)。

我提出了以下代码,到目前为止似乎完全符合我的预期,并且基于TuKsn的答案,但是增强了一点:

  • 默认工作( gedit ... ),无需使用F12或其他一些快捷方式(调用未经过滤的使用/usr/bin/gedit ... )。
  • 在作为后台任务终止时显示输入的命令名称。

仍然可以推广一下,但是现在,如果你需要对其他命令采用相同的处理方法,请为需要相同filter的每个其他命令名复制gedit()函数。

 # solution adapted from: http://askubuntu.com/questions/505594 # TODO: use a list of warnings instead of cramming all of them to a single grep. # TODO: generalize gedit() to allow the same treatment for several commands # without duplicating the function with only a different name # output filter. takes: name_for_history some_command [arguments] # the first argument is required both for history, but also when invoking to bg # such that it shows Done  ... instead of eg Done /usr/bin/gedit ... suppress-gnome-warnings() { # $1 is the name which should appear on history but is otherwise unused. historyName=$1 shift if [ -n "$*" ]; then # write the real command to history without the prefix # syntax adapted from http://stackoverflow.com/questions/4827690 history -s "$historyName ${@:2}" # catch the command output errorMsg=$( $* 2>&1 ) # check if the command output contains not a (one of two) GTK-Warnings if ! $(echo $errorMsg | grep -q 'Gtk-WARNING\|connect to accessibility bus'); then echo $errorMsg fi fi } gedit() { suppress-gnome-warnings $FUNCNAME $(which $FUNCNAME) $@ } 

还有一个更好的版本(方式更小,完全通用,不需要重写历史,因为按原样调用,更好的是每行过滤而不是整个输出):

 # generates a function named $1 which: # - executes $(which $1) [with args] # - suppresses output lines which match $2 # eg adding: _supress echo "hello\|world" # will generate this function: # echo() { $(which echo) "$@" 2>&1 | tr -d '\r' | grep -v "hello\|world"; } # and from now on, using echo will work normally except that lines with # hello or world will not show at the output # to see the generated functions, replace eval with echo below # the 'tr' filter makes sure no spurious empty lines pass from some commands _supress() { eval "$1() { \$(which $1) \"\$@\" 2>&1 | tr -d '\r' | grep -v \"$2\"; }" } _supress gedit "Gtk-WARNING\|connect to accessibility bus" _supress gnome-terminal "accessibility bus\|stop working with a future version" _supress firefox "g_slice_set_config" 

它也是一种解决方法,但您不必将其应用于每个应用程序。

将此内容写入.bashrc ,您可以将此包装器与F12(或选择其他键)一起使用来抑制警告:

 # output filter of() { if [ -n "$*" ]; then # write the real command to history without the prefix "of" history -s "$*" # catch the command output errorMsg=$( $* 2>&1 ) # check if the command output contains not a GTK-Warning if ! $(echo $errorMsg | grep -q 'Gtk-WARNING'); then echo $errorMsg fi fi } # write the function "of" before every command if the user presses F12 bind '"\e[24~": "\e[1~ of \e[4~\n"' 

我实际上在C中编写了hide-warnings工具 ,我发现它比上面显示的脚本更容易使用。 此外,它将默认写入写入stdout的所有输出(因为Gtk和其他警告被发送到stderr因此它默认解析stderr而不是stdout )。

上面脚本的一个大问题是它不会向控制台写任何内容,即使它与正则表达式不匹配,直到完成。 这是因为它将所有数据保存在变量中,然后在完成后grep该变量。 这也意味着它可能会使用大量内存将输出保存在该变量中(至少应将其保存在临时文件中。)最后,从我所看到的情况来看,如果任何一行匹配,grep将阻止任何显示。 也许不完全是你想要的。

该工具可以在一个简单的别名中使用,如下所示:

 alias gvim="hide-warnings gvim" 

(我使用gvim ……我相信它也适用于gedit 。)

该文件是自包含的,没有C库以外的依赖项,因此您可以获得一个副本并轻松编译和安装它:

 gcc hide-warnings.c -o hide-warnings sudo cp hide-warnings /usr/bin/. 

文件中还有一些文档,您可以使用--help编译为快速文档。

我本人想找一个解决这类问题的工具。

我提供的答案的问题如下:

  • 重要的是stdout和stderr不会聚合到一个流中
  • 我无法调用命令,过滤所有输出直到它终止,并在最后打印它(即解决方案必须正确地输出输出)
  • 我想尽可能保留stdout和stderr消息的顺序

我很欣赏我用Bash做过的尝试,但是,我没有找到一个能够达到上述所有3个条件的解决方案。

我的终极解决方案是用NodeJS编写的,据我所知,它不会安装在很多linux机器上。 在选择编写JS版本之前,我尝试在python中对其进行编码,并发现async IO库非常难看并且已经破解,直到非常新版本的python(~3.5在某些较新的发行版中可以开箱即用)。

最小化依赖关系是选择python的唯一理由,所以我放弃了NodeJS,它有一组非常低级别,异步的IO库。

这里是:

 #!/usr/bin/env nodejs const spawn = require('child_process').spawn function usage() { console.warn('Usage: filter-err   [ ...]') process.exit(1) } function main(err_regex, cmd_arr) { let filter = new RegExp(err_regex) let proc = spawn(cmd_arr[0], cmd_arr.slice(1), { shell: true, stdio: ['inherit', 'inherit', 'pipe'] }) proc.stderr.on('data', (err) => { err = err.toString('utf8') if (! err.match(filter)) process.stderr.write(err) }) proc.on('close', (code) => process.exit(code)) } const argv = process.argv if (argv.length < 4) usage() else main(argv[2], argv.slice(3)) 

要使用此脚本,您可以将这些行添加到.bashrc:

 alias gimp='filter-err "GLib-[^ ]*-WARNING" gimp' 

您选择运行的子进程将inheritancestdin,因此您可以自由使用BASH管道或重定向。