Як визначити термінал зі скрипту?


8

І не кажіть " $TERM" - це завжди xterm.

Як bashскрипт може сказати, в якому терміналі він працює, зокрема, чи це iTerm, Terminal.app чи насправді xterm?

Я запитую, бо resetне працює з терміналу на Terminal.app та iTerm2. iTerm2, однак, розпізнає послідовність виходу для скидання терміналу ( \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чи iTerm, щоб надіслати правильну послідовність виходу.

Чи є спосіб (навіть якщо мені потрібно ioctl) запитати термінал, що це насправді ?

¹ Для цілей цього питання скидання має очистити екран, скинути курсор і витерти буфер прокрутки.


Ну, це особливість, а не помилка, або так вони кажуть. Що станеться, якщо відкрити Terminal.appпараметри, вкладку термінала та встановити лінії прокрутки на 0? Це відключає будь-який і весь текст над поточним рядком або просто що-небудь вгорі екрана? Я знаю, це не саме те, про що ви просили, варто зняти.
nitro2k01

@ nitro2k01: Я не впевнений, що це може досягти? Я хочу прокрутки. Я просто хочу, щоб я міг очищати це час від часу, бажано за допомогою reset, оскільки це знають мої пальці.
Танатос

Що стосується вашої проблеми "скидання": для уточнення, ви очікуєте, що resetкоманда очистить вміст прокрутки термінального емулятора, але це не гарантовано, тому що прокрутка - це особливість емулятора терміналу, а не справді частина терміналу. Однак Terminal підтримує розширення послідовності відключення ED (Erase in Display) для видалення прокрутки ESC [ 3 J. Ви можете очистити екран, а потім скористатися цим, наприклад,reset && printf '\e[3J’
Chris Page

Дивіться мою відповідь тут apple.stackexchange.com/a/113168/6883 для отримання більш детальної інформації про розширення "Стерти в дисплей".
Кріс Пейдж

@ChrisPage: Я розумію, що термінали - вигадливі речі, але якщо ти оголосиш себе як xterm(наскрізний TERM=xterm), я очікую, що ти будеш емулювати надмножину XTerm, яка очищає її прокрутку при скиді. (Так само, як якщо б ви надіслали послідовність втечі для "блакитного", ви очікували б блакитного.) Звичайно, мій xterm каже мені Erase is backspace., що я нічого не вдячний; це просто дратує.
Танатос

Відповіді:


10

Використовуйте $TERM_PROGRAM.

iTerm встановлює його iTerm.app, а Terminal.app - Apple_Terminal.


Хе, гаразд, це явно краще, ніж мій злом, +1 :). Хоч має працювати для будь-якого термінального емулятора, хоча не лише цих двох.
тердон

Не існує єдиного способу виявлення кожного емулятора терміналу. Наприклад, для xterm ви можете перевірити наявність змінної $ XTERM_VERSION. Це допоможе подбати про те, що, мабуть, три найпопулярніші емулятори в OS X.
Кріс Пейдж

Прийнявши це, це гарний початок. На жаль, це не так просто, оскільки ця змінна недоступна в сеансі SSH. Я підозрюю, що є конфігурації, які я можу редагувати, щоб переслати її.
Танатос

1
@Thanatos sshd_config«S AcceptEnvймовірно. Оскільки це (ваша оболонка працює на іншому хості, ніж той, на якому працює ваш Термінал) є дуже важливою інформацією, вона дійсно повинна бути частиною питання.
Даніель Бек

@DanielBeck: Це не зовсім так; Я хотів би зробити те саме місцево та віддалено. Що я збираюся зробити, це те, що введення «скидання» в термінал викликає скидання терміналу, незалежно від того, працюю я на OS X або Linux, працюю локально або віддалено. Я це відредагував у питанні.
Танатос

1

$TERMне має нічого спільного з емулятором терміналу, який зараз працює, це просто термінал за замовчуванням і його взагалі можна встановити на що завгодно. Для отримання імені емулятора термінала, який ви працюєте, ви можете використовувати psPID батьківського процесу вашої поточної оболонки.

ПРИМІТКА. На 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
    

Не працює в ОС X:ps: illegal option -- f
Даніель Бек

@DanielBeck проклятий стиль BSD, спасибі Чи можете ви спробувати ще раз із оновленою версією? Додавання -параметра до того, як параметри повинні працювати відповідно до OSX man ps.
тердон

Краще, але все одно не працює. Формат виводу різний (PID є $2, PPID є $3), і батьківський процес оболонки може бути login(залежно від конфігурації терміналу), з різними параметрами. Однак його батьківський процес є Terminal. --no-headersне існує, вам знадобиться щось на кшталт tail -n1. А оскільки в усіх процесах з інтерфейсом є аргумент-psn_0_... , теж awk '{print $NF}'не працює.
Даніель Бек

@DanielBeck добре збивається тоді. Добре, дякую, я дам зрозуміти, що це не вдається на OSX.
тердон

Зауважте, що це працює лише локально. Ви не можете використовувати цей підхід, щоб визначити, який емулятор терміналу використовується на віддаленому клієнті. Найкраща відповідь - шукати такі змінні, як $ TERM_PROGRAM (як згадується у відповіді @ DanielBeck) та $ XTERM_VERSION для виведення програми емулятора.
Кріс Пейдж

0

Ось портативний спосіб отримати ім’я або шлях батьківського процесу:

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

Terminal.app:

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

Зауважте, що якщо Terminal.app встановлений для відкриття нових оболонок з оболонкою для входу за замовчуванням, батьківським процесом оболонки є, loginа не термінал.

commКолона є повним шляхом команди в OS X і ім'я команди усічений до 15 символів в реалізації PROCPS в Linux.


Спробував в iTerm і отримав login- Чи налаштовував я свій профіль деякий час назад, щоб запустити команду login -fp danielbeck?
Даніель Бек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.