Как остановить gedit (и другие программы) для вывода предупреждений GTK и т.п. в моем терминале?

32

Я запускаю удивительный оконный менеджер на верном после обновления от 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 не единственный, кто любит портить терминал.

FUZxxl
источник
2
Почему вы не можете использовать 3 варианта, которые вы упомянули?
Тим
Я не думаю, что вы можете отключить эти предупреждения, но, как спросил @Tim, что вы имеете против использования 3-х вариантов, которые могли бы решить вашу проблему?
ElefantPhace
7
Спасибо, я знаю, как сделать перенаправление оболочки. Причина, по которой я не хочу этого делать (и прямо заявляю об этом), заключается в том, что эти предупреждения также появляются во многих других программах. Параметр конфигурации для dbus или любого другого компонента, который генерирует эти предупреждения, отключит предупреждение для всех программ, которые его генерируют. С перенаправлением я должен применить обходной путь (который не является решением) для каждой программы в отдельности.
FUZxxl
@FUZxxl Я не могу заставить свой gedit последовательно выводить ошибки. Но мне любопытно, если export GCONF_DEBUG="no"бы что-нибудь сделало
Дан
@ dan08 Нет, не делаю трюк.
FUZxxl

Ответы:

17

Во-первых, меня также раздражает, что эти предупреждения появляются в готовой Ubuntu без «правильного» метода их отключения, который я мог бы найти (кажется, что наиболее распространенным «решением» является установка gir1.2-gtksource-3.0который, кажется, не работает, так как он уже установлен, или игнорировать их - но я хочу полностью их отключить, поскольку они просто делают мой терминал шумным).

Я придумал следующий код, который до сих пор, кажется, ведет себя именно так, как я ожидал, и основан на ответе TuKsn, но немного улучшает его:

  • Работайте по умолчанию ( gedit ...) без необходимости использовать F12 или какой-либо другой ярлык (чтобы вызвать нефильтрованное использование /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"
AVIH
источник
Это отличный ответ. Я буду использовать это в будущем.
FUZxxl
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"'
TuKsn
источник
Это выглядит немного лучше. Я собираюсь проверить это.
FUZxxl
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после компиляции для быстрой документации.

Более новая версия , которая в какой-то момент будет использовать библиотеку advgetopt, находится на C ++.

Алексис Уилке
источник
Ссылка мертва.
Армин Риго
@ArminRigo, ах! Это переехало. Здесь я поместил новую ссылку на последнюю версию, прежде чем она была перенесена, потому что теперь это C ++. Также есть ссылка на версию C ++. Версия C больше не изменится.
Алексис Вильке
0

Я сам искал утилиту для решения такого рода проблем.

Мои проблемы с предоставленными ответами следующие:

  • важно, чтобы stdout и stderr не объединялись в один поток
  • Я не могу вызвать команду, отфильтровать все выходные данные, пока они не завершатся, и распечатать их в конце (т. Е. Решение должно правильно выводить выходные данные)
  • Я хотел бы максимально сохранить порядок сообщений stdout и stderr

Я ценю попытки, которые я видел, чтобы сделать это с Bash, однако мне не удалось найти решение, которое выполнило бы все 3 условия, описанные выше.

Мое окончательное решение написано на NodeJS, который, как я понимаю, не будет установлен на многих Linux-блоках. Прежде чем написать версию JS, я попытался закодировать ее на python и обнаружил, что библиотека асинхронного ввода-вывода довольно уродлива и не работает до ОЧЕНЬ последних версий python (~ 3.5, которые доступны в некоторых новых дистрибутивах).

Минимизация зависимостей была ЕДИНСТВЕННОЙ причиной выбора python, поэтому я отказался от него для NodeJS, который имеет замечательный набор библиотек для несколько низкоуровневых асинхронно-ориентированных операций ввода-вывода.

Вот:

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

Подпроцесс, который вы выберете для запуска, унаследует стандартный ввод, поэтому вы можете свободно использовать каналы BASH или перенаправление.

Шейн
источник