Как проверить, какой эмулятор терминала сейчас используется?

15

У меня есть gnome-терминал и установленный Guake. Я хочу, чтобы при запуске эмуляторы терминала отображали разные сообщения при запуске. Какой код я должен написать в .bashrc, чтобы это было достигнуто?

VedVals
источник

Ответы:

10

Эта функция должна делать работу:

container() {
    pid=$$
    while true; do
        pid=$(ps -h -o ppid -p $pid 2>/dev/null)
        case $(ps -h -o comm -p $pid 2>/dev/null) in
        (gnome-terminal) echo "Running in gnome terminal";return;;
        (xterm) echo "Running in xterm";return;;
        (rxvt) echo "Running in rxvt";return;;
        (python) if [ ! -z "$(ps -h -o args -p $pid 2>/dev/null | grep guake)" ]; then echo "Running in Guake"; return; fi ;;
        esac
        [[ $(echo $pid) == 1 ]] && break
    done
}
container
jlliagre
источник
Хороший ответ! Не забудьте на самом деле вызвать функцию containerпосле определения.
Рощ
Я ожидал, что это будет очевидно, но вы правы, ответ обновлен соответственно.
Jlliagre
@jlliagre Я попробовал код. Он работает гладко на gnome-Terminal, но у Guake есть проблемы. Это не дает никакого выхода. Вместо этого он как бы зависает, словно в тупике. Я должен Ctrl + C, чтобы использовать его. Не совсем понял код, поэтому не знаю, где он идет не так.
VedVals
Код исправлен. Я пропустил guake, запускаемый python, и у меня была ошибка, препятствующая выходу функции. Спасибо за ответ.
Jlliagre
Извини, чувак, все еще не совсем работает. Выдает ошибку bash: [: too many arguments. Получил bash v4.2.24, python v2.7.3, если это поможет.
ВедВалс
10

Попробуй это:

echo $TERM

Это более авторитетно, но может быть испорчено вашими программами. Однако, по моему, он говорит, xtermа по ttys говорит linux, что, я думаю, означает Linux Console.

CMCDragonkai
источник
2
$TERMпеременная, которая ссылается на спецификацию как самоотчетную, которую использует эмулятор терминала, а не на сам эмулятор. Например, в моей системе echo $TERMвозвращается, xtermхотя на самом деле я запускаю lxterminal. То, что происходит, - это самоотчеты о соблюдении условий. lxterminal на самом деле не полностью совместим с xterm, поэтому вам следует остерегаться. Спецификационные файлы обычно находятся в /usr/share/terminfo.
Стажер
7

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

В bash, zsh и т.д .:

basename "/"$(ps -f -p $(cat /proc/$(echo $$)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

С рыбной раковиной:

basename "/"(ps -f -p (cat /proc/(echo %self)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')
mamiu
источник
Однако обратите внимание, что это будет перехватывать программные аргументы, когда эмулятор терминала запускается вместе с ними.
Робобенкляйн
Это работает, если я подключен по SSH?
user3731622
@ user3731622 не будет! Вы должны будете отправить его от клиента.
Энрико
2

На многих системах Linux echo $TERMвозвращение xtermсм. Пост постера выше.

Чтобы получить действующий терминал, сделайте это:

1: Закройте все запущенные в данный момент терминальные экземпляры.

2: Откройте новый терминал, используя ваш обычный метод.

3: введите команду следующим образом:

ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)

4: Возвращение должно быть примерно таким:

lxterminal --geometry=135x20

Вот разбивка:

Итак: psэто «статус процесса»

Параметр ps -oотображает информацию, связанную с указанным пробелом или разделенным запятыми списком ключевых слов Звучит сложно, но не совсем. (пробел или запятая) указан отдельно (список ключевых слов).

Итак, (список ключевых слов) - это 'cmd='только одно ключевое слово в списке. Итак, просто с просьбой отобразить команду на открытие терминала.

опция ps -p"by id процесса" Ого, это очень хорошая опция для ps. Проблема в том, что вы должны передать ps этот идентификатор процесса. Итак, как получить идентификатор процесса? Развернем выражение $(ps -o 'ppid=' -p $$)

Здесь мы должны начать думать немного глубже. Я хотел бы изобрести этот bash однострочник, но я этого не сделал. Я думаю, что украл его из https://wiki.archlinux.org/ где-то, я не мог найти снова. Эти парни потрясающие, но много раз я не могу понять, что они говорят делать, пока не проведу много исследований. Что мы можем сделать, это понять это сейчас, потому что я объясню.

так что мы знаем, $является оператором расширения в Bash. Мне нравится думать "развернуть". Итак, $(foo -opt bar)развернем или развернем "foo -opt bar". Но в bash, единственная круглая скобка (...)открывает подоболочку.

Итак, $(foo -opt bar)расширяется "foo -opt bar", как запускается в дочерней оболочке . Очень странно и трудно понять.

Итак, теперь мы снова запускаем почти идентичную команду, ps -o 'ppid=' -p $$но на этот раз ps, состояние процесса, показывает нам, что он может видеть из экземпляра дочерней оболочки .

-oсписок ключевых слов, только одно ключевое слово, как и раньше, но ppid=это напрямую запрашивает идентификатор процесса родительской оболочки !! ИЗ ВНУТРЕННЕЙ ОБОЛОЧКИ! Очень умно, да? Я так взволнован, когда я могу понять это!

-pопять же "по идентификатору процесса", а в bash $$- идентификатор процесса.

Если вы вызываете ps -o 'ppid=' -p $$или любую другую команду, запрашивающую $$напрямую из первой оболочки, он может сказать pid = 1, или pid из xWindow, или из вашей настольной программы, или вы можете получить реальный pid оболочки. Если вы спросите много раз, вы можете получить разные ответы каждый раз!

Но если вы вызовете дочь и спросите ее «Кто твой папочка», она скажет тебе! Очень умно. Я хотел бы быть таким гением, чтобы изобрести этот метод.

stazher
источник
ОК, поэтому AU не допустит правильной разбивки в пределах одного поста. Извините, не желаю бороться с системой блогов и делать несколько постов. Может быть, вы можете получить идею.
Стажер
Ваш другой ответ кажется сложным и информативным комментарием к этому ответу, а не ответом на вопрос ... Было бы здорово, если бы вы могли объединить два своих ответа в один, удалить один из них и добавить к нему, чтобы он полностью отвечает на вопрос. Используйте ----, чтобы нарисовать линию в середине? Также есть кнопка.
Занна
Я думаю, что я ответил на вопрос ОП точно и подробно. Вы прыгнули на меня, прежде чем я успел понять систему редактирования блога и закончить. Принеси вниз голоса, я к этому привык.
Stazher
1
Не думаю, что я подскочил на вас, я просто делал обзор ... спасибо за то, что сделали ваш пост более полным
Zanna
Благодарю за ваш ответ. Извините, может быть, я прыгнул на вас. Я очень извиняюсь.
17
1

Использование pstreeи awkсамый простой способ:

pstree -sA $$ | awk -F "---" '{ print $2 }'

Объясняя

  1. Выведите на экран дерево процессов с pstreeof $$(атуальный процесс).
  2. В pstreeаргументах:

    • -s: показать родителей процесса
    • -A: отображать вывод в чистом ASCII.
  3. awkИнструмент сканирование шаблона и -Fаргумент используется для разделения процессов.

  4. В завершение '{ print $2 }'указывается awkвыводить только 2-й шаблон соответствия (в данном случае это имя эмулятора терминала).
silvadev
источник
Вы уверены $2? В моем случае, то, что передается, на awkсамом деле systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Энрико Мария Де Анджелис
@EnricoMariaDeAngelis Ya. Спасибо за ваше наблюдение. В моем случае эмулятор терминала инициализируется непосредственно в сервисе systemd. Я снова проверяю код и редактирую его с исправлением.
Сильвадев
Это не работает, когда я использую сочетание клавиш для запуска эмулятора. На XFCE я получаю xfsettingsdвместо терминала, который я использую.
Майкл Хоффманн
Работает лучше, если начать с конца:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff
0

Вы правы, я только сделал ответ на главный вопрос, а не вопрос в теле. Итак, поехали, Боб и твой дядя.

Я не уверен, о чем был случай переключения, в одном ответе, показанном выше. Такой чехол переключения не нужен. Мой скрипт ~ / .bashrc - это всего лишь одна простая строка, все команды echo просто для удовольствия. Как объяснить...

Любой термин при запуске читает ~ / .bashrc и выполняет все команды, которые он увидит в .bashrc. Таким образом, независимо от того, какой термин вызывается, он будет читать .bashrc и выполнять команды, поэтому единственной структурой, необходимой в .bashrc, будет изменение поведения или исключение того или иного термина. Желаемое поведение - чтобы каждый член выполнял одну и ту же команду, поэтому переключение регистра не требуется. Терминал сам расскажет вам, как его называли, поэтому нет необходимости различать.

Примечание (1) Я не тестировал guake, но работает для всех остальных, упомянутых в первом ответе jlliagre.

Примечание (2) Из-за форматирования в уценке для вики вы не можете вырезать и вставлять, как показано. Вы должны удалить каждый обратный удар , включая удаление символов подчеркивания, и добавить фактический обратный удар без пробела перед psили после -p $$).

скрипт для ~ / .bashrc

# show welcome message for actual terminal in use
echo "Welcome.  You are attempting to use"
echo ""
echo _backtick_ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)_backtick_
echo ""
echo "Good Luck and God Speed."

Это было очень весело. Я добавил это в свой собственный ~ / .bashrc.

stazher
источник
согласно примечанию (1), тестировали на тильде, отлично работает. Guake похож на Tilda, но написан на python, поэтому до сих пор не знаю о Guake.
Stazher
0

если вы используете bash, я думаю, эта команда поможет вам:

which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))

Ван Шидонг
источник
0

Если вы использовали ZSH, есть лучшее (более быстрое) решение, которое использует только встроенные функции ZSH и манипулирует /proc/$pid/{stat,cmdline}напрямую.

get-terminal-emulator() {
    if [[ $TTY = "/dev/tty"* ]]; then
        echo "linux-console"
        return
    fi
    local pid=$$ name=''
    while true; do
        proc_stat=(${(@f)$(</proc/${pid}/stat)})
        name=${proc_stat[2]//[()]/}
        case "${name}" in
            gnome-terminal|konsole|rxvt|xterm)
                echo "${name}"; return ;;
            python*)
                local cmdline=(${(@f)$(</proc/${pid}/cmdline)})
                if [[ "$cmdline" =~ "\\bguake.main\\b" ]]; then
                    echo "guake"; return
                fi
                ;;
        esac
        if test "$pid" = "1" -o "$pid" = ""; then
            echo "unknown"
            return
        fi
        pid=${proc_stat[4]}       
    done
}
Андре фон Кугланд
источник