¿Cómo evitar que gedit (y otros programas) generen advertencias GTK y similares en mi terminal?

32

Estoy ejecutando el impresionante administrador de ventanas en trusty después de haber actualizado de raring. Mi entorno de escritorio intencionalmente no tiene todos los demonios Gnome / Freedesktop ejecutándose; no los quiero.

Cuando ejecuto geditdesde una terminal como esta:

gedit file

Emite mensajes como este en mi terminal cada vez que presiono enter o guardar o en varias otras ocasiones:

(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

Entiendo el significado de esta advertencia y he decidido que no me importa.

¿Cómo puedo desactivar este tipo de advertencia? Por "apagar", no me refiero a ninguna de estas soluciones o soluciones similares:

  • canalizando la salida de gedit en /dev/null
  • escribir un script de envoltura que canaliza la salida de gedit en /dev/null
  • creando un alias que canaliza la salida de gedit en /dev/null

Estas soluciones alternativas no son aceptables, ya que deben aplicarse individualmente a cada aplicación Gnome; gedit no es el único al que le gusta estropear el terminal.

FUZxxl
fuente
2
¿Por qué no puedes usar las 3 opciones que mencionaste?
Tim
No creo que pueda desactivar esas advertencias, pero como @Tim le preguntó, ¿qué tiene en contra de usar las 3 opciones que resolverían su problema?
ElefantPhace
77
Gracias, sé cómo hacer la redirección de shell. La razón por la que no quiero hacer esto (y afirmar explícitamente eso) es que estas advertencias también aparecen en muchos otros programas. Una opción de configuración para dbus o cualquier componente que genere estas advertencias desactivará la advertencia para todos los programas que la generen. Con la redirección, tengo que aplicar la solución (que no es una solución) a cada programa individualmente.
FUZxxl
@FUZxxl No puedo hacer que mi gedit muestre errores de manera consistente. Pero tengo curiosidad por saber si export GCONF_DEBUG="no"haría algo
Dan
@ dan08 No, no estoy haciendo el truco.
FUZxxl

Respuestas:

17

Primero, también me resulta molesto que estas advertencias aparezcan en un Ubuntu listo para usar, sin un método "adecuado" para deshabilitarlas, lo que pude encontrar (parece que la "solución" más común es instalar gir1.2-gtksource-3.0que no parece funcionar ya que ya está instalado, o ignorarlos, pero quiero suprimirlos por completo ya que solo hacen que mi terminal sea ruidosa).

Se me ocurrió el siguiente código que hasta ahora parece comportarse exactamente como lo esperaba, y se basa en la respuesta de TuKsn, pero lo mejora un poco para:

  • Trabaja por defecto ( gedit ...) sin necesidad de usar F12 o algún otro acceso directo (para invocar el uso sin filtro /usr/bin/gedit ...).
  • Muestra el nombre del comando ingresado cuando finaliza como una tarea en segundo plano.

Todavía se puede generalizar un poco, pero por ahora, si necesita el mismo tratamiento para otros comandos, duplique la gedit()función para cada nombre de comando que necesita el mismo filtro.

# 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) $@
}

Y una versión mejor (mucho más pequeña, totalmente genérica, sin necesidad de reescribir el historial, ya que se invoca tal cual, y mejor para filtrar por línea en lugar de la salida completa):

# 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"
avih
fuente
Esta es una respuesta genial. Usaré esto en el futuro.
FUZxxl
2

También es una solución, pero no tiene que aplicar esto para cada aplicación.

Escríbele esto a tu .bashrcy puedes usar este contenedor con F12 (o elegir otra tecla) para suprimir las advertencias:

# 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"'
TuKsn
fuente
Eso se ve un poco mejor. Voy a probar eso.
FUZxxl
1

De hecho, escribí la herramienta hide-warnings en C, que encuentro mucho más fácil de usar que el script que se muestra arriba. Además, escribirá toda la salida escrita stdoutde forma predeterminada (porque el Gtk y otras advertencias se envían a, stderrpor lo que stderrno se analiza stdoutde manera predeterminada).

Un gran problema con el script anterior es que no escribirá nada en su consola, incluso si no coincide con la expresión regular, hasta que se haga. Esto se debe a que guarda todos los datos en una variable y luego grep esa variable una vez hecho. También significa que guardará la salida en esa variable, posiblemente usando mucha memoria (al menos debería guardarla en un archivo temporal). Finalmente, por lo que puedo ver, el grep evitará cualquier visualización si alguna línea coincide . Quizás no sea exactamente lo que quieres.

La herramienta se puede usar en un alias simple como este:

alias gvim="hide-warnings gvim"

(Yo uso gvim... estoy seguro de que funcionaría gedittambién).

El archivo es autónomo, sin dependencias distintas de la biblioteca C, por lo que puede obtener una copia y compilarlo e instalarlo fácilmente:

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

Hay más documentación en el archivo y puede usar --helpuna vez compilado para documentos rápidos.

La versión más nueva , que en algún momento utilizará la biblioteca advgetopt, está en C ++.

Alexis Wilke
fuente
El enlace está muerto.
Armin Rigo
@ArminRigo, ¡Ah! Se movio. Aquí puse un nuevo enlace al último antes de que se moviera porque ahora es C ++. También hay un enlace a la versión C ++. La versión C no cambiará más.
Alexis Wilke
0

Estaba buscando una utilidad para resolver este tipo de problema, yo mismo.

Mis problemas con las respuestas proporcionadas son las siguientes:

  • es importante que stdout y stderr no se agreguen en una sola secuencia
  • No puedo invocar un comando, filtrar todo el resultado hasta que finalice e imprimirlo al final (es decir, la solución debe transmitir el resultado correctamente)
  • Me gustaría preservar el orden de los mensajes stdout y stderr tanto como sea posible

Aprecio los intentos que he visto para hacer esto con Bash, sin embargo, no pude identificar una solución que lograra las 3 condiciones descritas anteriormente.

Mi solución final está escrita en NodeJS, que entiendo que no se instalará en muchas cajas de Linux. Antes de elegir escribir la versión JS, intenté codificarla en python, y descubrí que la biblioteca asíncrona de IO es bastante fea y está rota hasta versiones MUY recientes de python (~ 3.5 que está disponible de fábrica en ALGUNAS distribuciones más recientes).

Minimizar las dependencias fue la ÚNICA razón para elegir Python, por lo que lo abandoné por NodeJS, que tiene un conjunto notable de bibliotecas para IO orientado asíncrono de bajo nivel.

Aquí está:

#!/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))

Para usar este script, puede agregar estas líneas a su .bashrc:

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

El subproceso que elija ejecutar heredará stdin, por lo que puede utilizar tuberías o redireccionamiento BASH.

Shane
fuente