Come impedire a gedit (e altri programmi) di inviare avvisi GTK e simili nel mio terminale?


32

Sto eseguendo il fantastico window manager su fidato dopo aver aggiornato da raring. Il mio ambiente desktop intenzionalmente non ha tutti i demoni Gnome / Freedesktop in esecuzione - non li voglio.

Quando eseguo geditda un terminale in questo modo:

gedit file

Emette messaggi come questo in tutto il mio terminale ogni volta che premo invio o salvataggio o in varie altre occasioni:

(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

Comprendo il significato di questo avviso e ho deciso che non mi interessa.

Come posso disattivare questo tipo di avviso? Per "disattivare", non intendo nessuna di queste o soluzioni alternative simili:

  • convogliare l'output di gedit in /dev/null
  • scrivere uno script wrapper che convoglia l'output di gedit in /dev/null
  • creando un alias che convoglia l'output di gedit in /dev/null

Queste soluzioni alternative non sono accettabili in quanto devono essere applicate individualmente a ciascuna applicazione Gnome - gedit non è l'unico a cui piace rovinare il terminale.


2
Perché non puoi usare le 3 opzioni che hai citato?
Tim

Non credo che tu possa disattivare quegli avvisi, ma come ha chiesto @Tim, cosa hai contro l'utilizzo delle 3 opzioni che potrebbero risolvere il tuo problema?
ElefantPhace,

7
Grazie, so come fare il reindirizzamento della shell. Il motivo per cui non voglio fare questo (e dichiararlo esplicitamente) è che questi avvisi compaiono anche in molti altri programmi. Un'opzione di configurazione per dbus o qualsiasi componente che genera questi avvisi disattiverà l'avviso per tutti i programmi che lo generano. Con il reindirizzamento, devo applicare la soluzione alternativa (che non è una soluzione) a ciascun programma individualmente.
FUZxxl

@FUZxxl Non riesco a far sì che il mio gedit emetta errori in modo coerente. Ma sono curioso di sapere se export GCONF_DEBUG="no"farebbe qualsiasi cosa
Dan,

@ dan08 No, non sto facendo il trucco.
FUZxxl

Risposte:


17

In primo luogo, trovo anche fastidioso che questi avvisi vengano visualizzati su un Ubuntu out-of-the-box, senza alcun metodo "corretto" per disabilitarli che potrei trovare (sembra che la "soluzione" più comune sia quella di installare gir1.2-gtksource-3.0che non sembra funzionare poiché è già installato o che li ignora, ma voglio eliminarli completamente poiché rendono il mio terminale rumoroso).

Ho trovato il seguente codice che finora sembra comportarsi esattamente come mi aspetto, ed è basato sulla risposta di TuKsn, ma lo migliora un po 'per:

  • Funziona di default ( gedit ...) senza la necessità di usare F12 o qualche altra scorciatoia (per invocare l'uso non filtrato /usr/bin/gedit ...).
  • Visualizza il nome del comando immesso quando termina come attività in background.

Può ancora essere generalizzato un po ', ma per ora, se hai bisogno dello stesso trattamento per altri comandi, duplica la gedit()funzione per ogni altro nome di comando che necessita dello stesso 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) $@
}

E una versione migliore (molto più piccola, completamente generica, non è necessario riscrivere la cronologia poiché invocata così com'è e migliore per il filtro per riga anziché per l'intero output):

# 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"

Questa è un'ottima risposta Lo userò in futuro.
FUZxxl,

2

È anche una soluzione alternativa, ma non è necessario applicarlo per ogni applicazione.

Scrivi questo al tuo .bashrce puoi usare questo wrapper con F12 (o scegliere un'altra chiave) per sopprimere gli avvisi:

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

Sembra leggermente migliore. Lo proverò.
FUZxxl

1

In realtà ho scritto lo strumento Nascondi avvisi in C che trovo molto più facile da usare rispetto allo script mostrato sopra. Inoltre, scriverà tutto l'output scritto per stdoutimpostazione predefinita (poiché Gtk e altri avvisi vengono inviati in stderrmodo che stderrnon analizzi stdoutper impostazione predefinita).

Un grosso problema con lo script sopra è che non scriverà nulla sulla tua console, anche se non corrisponde al regex, fino al termine. Questo perché salva tutti i dati in una variabile e poi grep quella variabile una volta fatto. Significa anche che salverà l'output in quella variabile probabilmente usando molta memoria (almeno dovresti salvarlo in un file temporaneo.) Infine, da quello che posso vedere, grep impedirà qualsiasi visualizzazione se una riga corrisponde . Forse non è esattamente quello che vuoi.

Lo strumento può essere utilizzato in un semplice alias come questo:

alias gvim="hide-warnings gvim"

(Uso gvim... Sono sicuro che funzionerebbe geditanche con .)

Il file è autonomo, nessuna dipendenza diversa dalla libreria C, quindi puoi ottenere una copia e compilarla e installarla facilmente:

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

C'è dell'ulteriore documentazione nel file e puoi usarla --helpuna volta compilata per documenti rapidi.

La versione più recente , che a un certo punto utilizzerà la libreria advgetopt, è in C ++.


Il link è morto.
Armin Rigo,

@ArminRigo, Ah! Si è mosso. Qui ho inserito un nuovo collegamento all'ultimo prima che si spostasse perché ora è C ++. C'è anche un collegamento alla versione C ++. La versione C non cambierà più.
Alexis Wilke,

0

Stavo cercando di trovare un'utilità per risolvere questo tipo di problema, me stesso.

I miei problemi con le risposte fornite sono i seguenti:

  • è importante che stdout e stderr non vengano aggregati in un flusso
  • Non posso invocare un comando, filtrare tutto l'output fino a quando non termina e stamparlo alla fine (ovvero la soluzione deve trasmettere correttamente l'output)
  • Vorrei preservare il più possibile l'ordine dei messaggi stdout e stderr

Apprezzo i tentativi che ho visto di fare questo con Bash, tuttavia, non sono riuscito a identificare una soluzione che ha raggiunto tutte e 3 le condizioni descritte sopra.

La mia soluzione definitiva è scritta in NodeJS, che capisco non verrà installata su molte scatole Linux. Prima di scegliere di scrivere la versione JS, ho tentato di codificarla in Python e ho scoperto che la libreria IO asincrona è piuttosto brutta e rotta fino alle versioni MOLTO recenti di Python (~ 3.5 che è disponibile immediatamente su alcune distro più recenti).

Ridurre al minimo le dipendenze era l'UNICA ragione per scegliere Python, quindi l'ho abbandonato per NodeJS, che ha una notevole serie di librerie per un IO orientato in qualche modo a basso livello e asincrono.

Ecco qui:

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

Per usare questo script, potresti aggiungere queste righe al tuo .bashrc:

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

Il sottoprocesso che scegli di eseguire erediterà lo stdin, quindi sei libero di usare le pipe BASH o il reindirizzamento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.