И не говори " $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}'
Вот что я получаю в своей системе, используя несколько разных терминалов:
terminator
$ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | awk '{print $NF}' /usr/bin/x-terminal-emulator
gnome-terminal
$ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | awk '{print $NF}' /usr/lib/gnome-terminal/gnome-terminal-server
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.