Bagaimana cara menghentikan gedit (dan program lain) dari mengeluarkan peringatan GTK dan sejenisnya di terminal saya?

32

Saya menjalankan window manager yang luar biasa dengan amanah setelah ditingkatkan dari raring. Lingkungan desktop saya sengaja tidak menjalankan semua daemon Gnome / Freedesktop - Saya tidak menginginkannya.

Ketika saya mengeksekusi geditdari terminal seperti ini:

gedit file

Ini menampilkan pesan seperti ini di seluruh terminal saya setiap kali saya menekan enter atau save atau pada berbagai kesempatan lain:

(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

Saya mengerti arti dari peringatan ini dan saya telah memutuskan bahwa itu tidak masalah bagi saya.

Bagaimana saya bisa mematikan peringatan semacam ini? Dengan "mematikan", saya tidak bermaksud salah satu dari ini atau solusi yang serupa:

  • memipipkan keluaran gedit ke /dev/null
  • menulis skrip wrapper yang menyalurkan output gedit ke /dev/null
  • membuat alias yang menyalurkan output gedit ke /dev/null

Penanganan masalah ini tidak dapat diterima karena harus diterapkan secara terpisah untuk setiap aplikasi Gnome - gedit bukan satu-satunya yang suka mengacaukan terminal.

FUZxxl
sumber
2
Mengapa Anda tidak dapat menggunakan 3 opsi yang Anda sebutkan?
Tim
Saya tidak berpikir Anda bisa mematikan peringatan itu, tetapi seperti yang diminta @Tim, apa yang Anda miliki dengan menggunakan 3 opsi yang akan menyelesaikan masalah Anda?
ElefantPhace
7
Terima kasih, saya tahu cara melakukan redirection shell. Alasan mengapa saya tidak ingin melakukan ini (dan secara eksplisit menyatakan itu) adalah bahwa peringatan ini juga muncul di banyak program lain. Opsi konfigurasi untuk dbus atau komponen apa pun yang menghasilkan peringatan ini akan mematikan peringatan untuk semua program yang menghasilkannya. Dengan pengalihan, saya harus menerapkan solusi (yang bukan solusi) untuk setiap program secara individual.
FUZxxl
@FUZxxl Saya tidak bisa mendapatkan kesalahan gedit untuk output secara konsisten. Tapi saya ingin tahu apakah export GCONF_DEBUG="no"akan melakukan apa pun
Dan
@ dan08 Tidak, tidak melakukan trik.
FUZxxl

Jawaban:

17

Pertama, saya juga merasa menjengkelkan bahwa peringatan ini muncul di Ubuntu out-of-the-box, tanpa metode "tepat" untuk menonaktifkannya yang bisa saya temukan (tampaknya "solusi" yang paling umum adalah menginstal gir1.2-gtksource-3.0yang sepertinya tidak berfungsi karena sudah diinstal, atau mengabaikannya - tapi saya ingin menekan mereka sepenuhnya karena mereka hanya membuat terminal saya berisik).

Saya datang dengan kode berikut yang sejauh ini tampaknya berperilaku persis seperti yang saya harapkan, dan didasarkan pada jawaban oleh TuKsn, tetapi sedikit meningkatkannya untuk:

  • Bekerja secara default ( gedit ...) tanpa perlu menggunakan F12 atau jalan pintas lainnya (untuk memohon penggunaan tanpa filter /usr/bin/gedit ...).
  • Menampilkan nama perintah yang dimasukkan saat berakhir sebagai tugas latar belakang.

Masih bisa digeneralisasi sedikit, tetapi untuk saat ini, jika Anda memerlukan perlakuan yang sama untuk perintah lain, duplikat gedit()fungsi untuk setiap nama perintah lainnya yang memerlukan filter yang sama.

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

Dan versi yang lebih baik (jauh lebih kecil, sepenuhnya generik, tidak perlu menulis ulang sejarah karena dipanggil apa adanya, dan lebih baik untuk memfilter per baris daripada seluruh 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"
avih
sumber
Ini jawaban yang bagus. Saya akan menggunakan ini di masa depan.
FUZxxl
2

Ini juga merupakan solusi, tetapi Anda tidak harus menerapkan ini untuk setiap aplikasi.

Tulis ini untuk Anda .bashrcdan Anda dapat menggunakan pembungkus ini dengan F12 (atau memilih kunci lain) untuk menekan peringatan:

# 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
sumber
Itu terlihat sedikit lebih baik. Saya akan mengujinya.
FUZxxl
1

Saya benar-benar menulis alat sembunyikan-peringatan di C yang menurut saya jauh lebih mudah digunakan daripada skrip yang ditunjukkan di atas. Juga, ia akan menulis semua output yang ditulis stdoutsecara default (karena Gtk dan peringatan lainnya dikirim ke stderrsehingga mem-parsing stderrbukan stdoutsecara default).

Satu masalah besar dengan skrip di atas adalah tidak akan menulis apa pun untuk konsol Anda, bahkan jika itu tidak cocok dengan regex, sampai selesai. Ini karena ia menyimpan semua data dalam suatu variabel dan kemudian mengambil variabel itu setelah selesai. Ini juga berarti bahwa itu akan menyimpan output dalam variabel yang mungkin menggunakan banyak memori (setidaknya Anda harus menyimpannya dalam file sementara.) Akhirnya, dari apa yang saya lihat, grep akan mencegah tampilan apa pun jika ada satu baris yang cocok . Mungkin tidak persis seperti yang Anda inginkan.

Alat ini dapat digunakan dalam alias sederhana seperti ini:

alias gvim="hide-warnings gvim"

(Saya menggunakan gvim... Saya yakin itu akan berhasil geditjuga.)

File ini mandiri, tidak ada dependensi selain dari C library, sehingga Anda bisa mendapatkan salinan dan dengan mudah mengkompilasi dan menginstalnya:

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

Ada beberapa dokumentasi lebih lanjut dalam file dan Anda dapat menggunakan --helpsekali dikompilasi untuk dokumen cepat.

Versi yang lebih baru , yang pada titik tertentu akan menggunakan perpustakaan advgetopt, ada di C ++.

Alexis Wilke
sumber
Tautannya sudah mati.
Armin Rigo
@ArminRigo, Ah! Itu bergerak. Di sini saya meletakkan tautan baru ke yang terbaru sebelum dipindahkan karena sekarang ini C ++. Ada juga tautan ke versi C ++. Versi C tidak akan berubah lagi.
Alexis Wilke
0

Saya mencari utilitas untuk menyelesaikan masalah semacam ini, saya sendiri.

Masalah saya dengan jawaban yang diberikan adalah sebagai berikut:

  • Adalah penting bahwa stdout dan stderr tidak dikumpulkan ke dalam satu aliran
  • Saya tidak dapat menjalankan perintah, memfilter semua output sampai berakhir, dan mencetaknya di akhir (yaitu solusi harus mengalirkan output dengan benar)
  • Saya ingin mempertahankan urutan pesan stdout dan stderr sebanyak mungkin

Saya menghargai upaya yang saya lakukan untuk melakukan ini dengan Bash, namun, saya gagal mengidentifikasi solusi yang mencapai semua 3 kondisi yang diuraikan di atas.

Solusi pamungkas saya ditulis dalam NodeJS, yang saya pahami tidak akan diinstal pada banyak kotak linux. Sebelum memilih untuk menulis versi JS, saya mencoba kode itu dalam python, dan menemukan perpustakaan IO async cukup jelek dan rusak sampai SANGAT versi terbaru dari python (~ 3.5 yang tersedia di luar kotak pada BEBERAPA distro yang lebih baru).

Meminimalkan dependensi adalah SATU-SATUNYA alasan untuk memilih python, jadi saya meninggalkannya untuk NodeJS, yang memiliki seperangkat pustaka yang luar biasa untuk IO tingkat rendah yang berorientasi pada tingkat rendah.

Ini dia:

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

Untuk menggunakan skrip ini, Anda dapat menambahkan baris ini ke .bashrc Anda:

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

Subproses yang Anda pilih untuk dijalankan akan mewarisi stdin, jadi Anda bebas menggunakan pipa BASH atau pengalihan.

Shane
sumber