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


32

从稀疏升级后,我就在Trusted上运行了出色的窗口管理器。我的桌面环境故意没有运行所有的Gnome / Freedesktop守护程序-我不希望它们。

当我gedit从这样的终端执行时:

gedit file

每当我按下Enter或保存或在其他各种情况下,它都会在我的终端上输出这样的消息:

(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并不是唯一一个喜欢弄乱终端的程序。


2
您为什么不能使用提到的3个选项?
蒂姆(Tim)

我认为您无法关闭这些警告,但是正如@Tim所问,您反对使用3个可以解决问题的选项吗?
ElefantPhace 2014年

7
谢谢,我知道如何进行外壳重定向。我不想这样做(并明确指出)的原因是,这些警告也出现在许多其他程序中。dbus或生成这些警告的任何组件的配置选项将关闭所有生成该警告的程序的警告。使用重定向,我必须将变通办法(不是解决方案)分别应用于每个程序。
2014年

@FUZxxl我无法获得一致的gedit输出错误。但是我很好奇是否export GCONF_DEBUG="no"会采取任何行动
2014年

@ dan08不,不是这个把戏。
2014年

Answers:


17

首先,我还感到烦恼的是,这些警告出现在开箱即用的Ubuntu上,没有找到可以禁用它们的“正确”方法(似乎最常见的“解决方案”是安装gir1.2-gtksource-3.0由于已安装或忽略它们似乎无法正常工作-但我想完全抑制它们,因为它们只会使我的终端嘈杂。

我提出了以下代码,到目前为止,这些代码似乎完全符合我的期望,并且基于TuKsn的回答,但将其增强为:

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

仍然可以概括一下,但是现在,如果您需要对其他命令进行相同的处理,请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 <name> ... instead of e.g. 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
# e.g. 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"

这是一个很好的答案。以后会用到。
FUZxxl 2015年

2

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

.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"'

看起来好多了。我要测试一下。
2014年

1

实际上,我用C 编写了隐藏警告工具,发现它比上面显示的脚本更易于使用。同样,它将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在编译后使用它们作为快速文档。

较新的版本使用C ++编写,该版本有时会使用advgetopt库。


链接已死。
Armin Rigo

@ArminRigo,啊!它感动了。在这里,我放置了一个指向最新版本的新链接,因为它现在是C ++。还有一个指向C ++版本的链接。C版本不再更改。
Alexis Wilke

0

我一直在寻找一种实用程序来解决此类问题。

我提供的答案存在以下问题:

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

我很欣赏使用Bash进行此操作的尝试,但是,我未能找到能够满足上述所有3个条件的解决方案。

我的最终解决方案是用NodeJS编写的,据我了解,它不会安装在许多linux机器上。在选择编写JS版本之前,我尝试用python对其进行编码,发现异步IO库非常丑陋且已损坏,直到非常新的python版本为止(〜3.5,在某些较新的发行版中都可用)。

最小化依赖关系是选择python的唯一原因,因此我将其放弃用于NodeJS,NodeJS具有一组出色的库,用于一些低级的,面向异步的IO。

这里是:

#!/usr/bin/env nodejs

const spawn = require('child_process').spawn

function usage() {
    console.warn('Usage: filter-err <error regex> <cmd> [<cmd arg> ...]')
    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'

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.