Как определить терминал по скрипту?

Как определить терминал по скрипту?

И не говори " $TERM" – это всегда xterm.

Как bashскрипт может определить, в каком терминале он запущен, в частности, iTerm, Terminal.app или вообще xterm?

Я спрашиваю, потому что resetне работает¹ из коробки в Terminal.app и iTerm2. iTerm2, однако, распознает escape-последовательность для сброса терминала ( \x1b]50;ClearScrollback\x07), и если бы я мог ее обнаружить, я мог бы переопределить resetс помощью псевдонима, который делает правильно. AFAICT, в Terminal.app отсутствует последовательность сброса, илюди прибегают к нелепым хакерским уловкам, чтобы обойти это.

Моя конечная цель — добиться resetодинаковой работы, независимо от того, работаю ли я на OS X или Linux, локально или удаленно через SSH. (Я не хочу запоминать, где именно, и полезно выполнять reset && command-that-outputs-a-bunchи иметь возможность работать с выходом на связь.) Terminal.app и iTerm мешают этому плану, поскольку реализуются resetнеправильно.

Это значит, что простого переопределения resetнедостаточно: если я работаю на машине Linux, то gnome-terminalдля отправки правильной escape-последовательности ей нужно знать, использую ли я Term или iTerm.

Есть ли способ (даже если мне нужен ioctl) спросить терминал, что это такое?Действительноявляется?

¹В рамках данного вопроса сброс должен очищать экран, сбрасывать курсор и стирать буфер прокрутки.

решение1

Использовать $TERM_PROGRAM.

iTerm устанавливает его в iTerm.app, а Terminal.app в Apple_Terminal.

решение2

$TERMне имеет ничего общего с запущенным в данный момент эмулятором терминала, это просто ваш терминал по умолчанию, и его можно настроить на что угодно. Чтобы узнать имя запущенного вами эмулятора терминала, вы можете использовать psдля получения PID родительского процесса вашей текущей оболочки.

ПРИМЕЧАНИЕ: Следующие действия не дадут результата на OSX, но должны работать на Linux.

PID вашего текущего процесса оболочки — $$. Оттуда вы можете использовать psдля отображения дерева процессов и вывода PID родительского процесса вашего текущего сеанса оболочки:

ps -axjf | awk -v pid=$$ '($2==pid){print $1}'

Затем вы можете передать этот PID psи сказать ему вывести имя команды:

ps -o comm=  $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}')

Это укоротит имя, этого должно быть достаточно, чтобы понять, но это может быть не очень хорошо для скриптинга. Чтобы получить полное имя, вы можете попробовать

ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | awk '{print $NF}'

Вот что я получаю в своей системе, используя несколько разных терминалов:

  1. terminator

    $ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    /usr/bin/x-terminal-emulator
    
  2. gnome-terminal

    $ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    /usr/lib/gnome-terminal/gnome-terminal-server
    
  3. xterm

    $ ps --no-headers $(ps axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    xterm
    

решение3

Вот переносимый способ получить имя или путь родительского процесса:

iTerm 2:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
/Applications/iTerm.app/Contents/MacOS/iTerm

gnome-терминал в Ubuntu:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
gnome-terminal

Терминал.приложение:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
login

Обратите внимание, что если Terminal.app настроен на открытие новых оболочек с помощью оболочки входа по умолчанию, то родительским процессом оболочки является loginне терминал.

Столбец commпредставляет собой полный путь к команде в OS X и имя команды, усеченное до 15 символов в реализации procps в Linux.

Связанный контент