Комментарии 44
Понравилось про вывод из одного терминала на другой
Про интересные реализации вряд ли скажу, пользуюсь обычным Gnome и не жалуюсь. А что вы имеете в виду под терминалом для телеграм бота? Эмулятор терминала — это графическая программа для возможности запуска терминалов внутри оконного интерфейса, так что не очень понимаю как тут связаны бот и терминал :) Возможно, вы хотите производить процессинг ввода и имеете в виду общение с ботом прямо в терминале, а не из отдельного графического приложения (то есть просто stdin/stdout)? Тогда ответ да — в этом вам помогут псевдотерминалы. Так, например, поступают ssh и screen.
Итак, вы запустили терминал и в нем работает Bash. Вы хотите из Bash запустить бота и общаться с ним? Извините, до сих пор не понимаю какова ваша цель)
Понял вас) Да, так можно. Например, для gnome-terminal: gnome-terminal -e 'telegram-bot'
. Просто передавайте параметром любую программу, которую необходимо запустить при создании процесса нового терминала. Думайте об этом параметре как о аргументе, передающемся в Си вызов exec()
.
Но вы всегда можете написать свой эмулятор терминала, который будет запускать только ваш бот :)
Зачет сдан. 5+.
А это Terminal:
<фото>
А в правом-нижнем углу фото — это год? ;-)
является каламбуром для «Born again» Shell, то есть «возрождённый» Shell
Здесь надо уточнить, что оригинальная оболочка sh
называется еще "оболочкой Борна" (в честь ее автора — Стивена Борна). Соответственно bash
— это Bourne again shell, в этом и каламбур. Без контекста не очень понятно (конечно, не для тех, кто уже знает).
Вот оставила она в raw-режиме, теперь как из него вернуться в нормальный? Предположим, что закрывать окно (если окно) — нельзя. Надо отдать команду (reset или stty sane), но сделать это не получается — нас не слышат, потому что icrnl выключено. Надо жать в этом случае не reset, а reset<Ctrl+J>. Потому что клавиша Enter генерирует не Ctrl+J (LF, код 10), а Ctrl+M (CR, код 13), и только уже в модуле дисциплины присутствие icrnl переводит его в тот код, что ожидает обычный ввод строки. «И сырость капает на клавишу ВК».
У сетевых админов маршрутизаторы ряда классических производителей типа Cisco, Juniper управляются, по крайней мере при начальном конфигурировании, через последовательный порт. Тоже надо понимать хотя бы основы, что оно такое и как может работать.
У эмбедщиков или у тех админов, что управляют машинками по IPMI, очень типичный вариант — serial console поверх IPMI, которую нужно ещё уметь настраивать и понимать её глюки (и там проблемы сильно выше описанной — я у, кажется, Dell видел реализацию, у которой внутри конвертировались даже не битовые потоки, а эмуляции напряжения на порту, между разными скоростями).
Или вот ещё — на моей прошлой работе была одна жутко специализированная и дорогущая проприетарная программа, которая работала по капризу автора как терминальная (были и другие варианты доступа, но считались не основными). Предполагалось, что ею будет управлять человек непосредственно с терминала, некоторые вещи можно было делать только через него. А надо было автоматизировать управление (запуск/останов, отдачу команд). Пришлось запускать под screenʼом через самопальный переходник, что запускал целевую программу под отдельным PTY, гонял данные туда-обратно, настраивал штатную дисциплину, слушал команды по управлению, мог вставлять от имени пользователя какие-то последовательности символов или рассказывать, что последнее она вывела…
Действительно глубокое погружение.
И на удивление качественно подготовленный материал, хороший стиль, в сравнении с большинством современных публикаций на Хабре.
Автор, пиши ещё!
Кроме беды с этим термином:
TTY Line Discipline (рус. — дисциплина линии)
«Дисциплина линии» — на редкость неудачный перевод для «line discipline».
Да, я в курсе, что именно такая калька применяется повсеместно. Но, к сожалению, она затрудняет понимание на русском языке.
Из-за такого перевода line discipline постоянно ассоциируют с линией связи терминала (т.к. tty действительно подразумевает наличие таковой), но никакого отношения ни к каким линиям line discipline не имеет.
Английское «line» в этом контексте на русский переводится исключительно как «строка», т.к. подразумевает последовательность символов до символа LF («line feed» — «перевод строки»).
Почему-то нигде переводчикам не приходит в голову называть строки линиями — ни в текстовых редакторах, ни в табличных процессорах, ни в тех же эмуляторах терминалов.
Поэтому «line discipline» — это строковый буфер, строковая политика, обработчик строки, на худой конец — дисциплина строки, но никак не дисциплина линии.
Из-за такого перевода line discipline постоянно ассоциируют с линией связи терминала (т.к. tty действительно подразумевает наличие таковой), но никакого отношения ни к каким линиям line discipline не имеет.
Да, объяснение про строку и правда звучит логично, но разве не по этой самой линии связи передавался ввод? Тогда и название было бы вполне оправдано.
но разве не по этой самой линии связи передавался ввод?
line discipline находится между приложением и драйвером терминала.
Ее задача — обеспечение построчного ввода/вывода (т.е. в первую очередь — задачи буферизации) с возможностью обработки метаинформации (в виде служебных символом в том же потоке). Для пользователей это, в частности, позволяет редактировать набираемую команду.
А «эта самая линия» находится «за» драйвером и в общем случае ее может вообще не быть — может быть ее эмуляция, до чего line discipline нет абсолютно никакого дела. Аналогом «этой самой линии» для псевдотерминала является связь
PTS<-->PTM
.Да, в конкретных имплементациях обрабатываемая метаинформация может включать в том числе управление «той самой линией» и тогде некоторые служебные символы могут транслироваться, например, в ioctl драйвера, но обычно задачи line discipline сводятся к простому форматированию текста.
Замечу одну неточность в вашем ответе:
Вы сказали, что связь между pty master и pty slave это аналог линии связи. Однако, ведь это не правда. Линия связи лежала перед UART устройством. Байты с UART устройства принимал UART драйвер и передавал их после обработки драйверу консоли. Сейчас заместо uart драйвера и драйвера консоли выступают PTM и PTS устройства. Дисциплина линии же все также лежит между этими двумя устройствами, но здесь нет никакой линии связи больше. Конечно, это не отдельная дисциплина линии, а экспортируется дисциплина одного из устройств. Линия связи ушла, но дисциплина линии осталась. Точно также, как и название TTY — очень много концепций сохранилось с тех времен, поэтому не забывайте, что, может быть, хоть и сейчас "дисциплина линии" это что-то непонятное, но если мы окунемся в прошлое, то название будет иметь смысл.
Это задача одного конкретного варианта дисциплины — которая называется «нормальной» или тоже «терминальной». В Linux это константа N_TTY среди констант вариантов дисциплины.
Могут быть выбраны другие line discipline. Вот отдельная программа установки дисциплины на TTY — заметьте, сколько разных дисциплин она знает, и все кроме одной — никаких «строк» не знают, в основном это сетевые стеки с пакетами. На программном уровне это ставится через TIOCSETD.
Нет, именно линии. Потому что такие дисциплины бывают:
- обычная терминальная — только тогда «строка» имеет хоть какое-то смысл в обработке;
- SLIP или PPP — тогда никаких строк нет, работа на уровне байтов; задача дисциплины — вылавливать пакеты, отправлять их в IP стек, в случае PPP — также отрабатывать управляющие пакеты протокола (или хотя бы передавать их в управляющий процесс);
- изредка — другие (вот большой список), в которых тоже нет строк.
Нет, именно линии.
Да, похоже вы правы.
Мне не приходилось работать с сетью через терминал.
И я всегда считал, что в этом случае, как часто бывает, существующий механизм line discipline был расширен на несвойственные ему изначально задачи.
Но вот предполагалась ли изначально, что дисциплина будет работать с бинарными пакетами, сейчас сказать не так просто — все это было в pre-git истории.
Ясно. Мне приходилось с обеих сторон — строить доступ по PPP и SLIP по модемному дозвону.
> Но вот предполагалась ли изначально, что дисциплина будет работать с бинарными пакетами, сейчас сказать не так просто — все это было в pre-git истории.
«Pre-git» история немного доступна. В Lionsʼ Book (подробная структура Bell Unix V6) описаны функции процессинга ввода-вывода как для терминала, но хардкодом, а не выбираемым модулем.
Расширение на сменные модули (с обычным терминальным процессингом как умолчательным) появилось, скорее всего, в 4.2BSD-4.3BSD, со введением dial-up и связей по постоянным линиям поверх последовательных портов. Но тут самая тёмная часть истории из-за закрытости исходников; 4.4BSD-Lite-based BSD системы — открытые — уже содержали line discipline как устоявшееся и почти идентичным кодом, что нас приводит таки во времена не позже общей 4.4.
Очень уж он любит вопрос «что такое терминал?».
В терминале запускается нужная программа с помощью вызова функции exec(). Обычно запускается какой-то Shell (например, Bash).Разрешите наивный вопрос. Разве exec не подразумевает замену вызывающей программы на вызываемую? И получается, что Shell у нас должен появиться вместо эмулятора терминала. Проясните, пожалуйста, этот момент.
Да, конечно же спавнится новый процесс и уже в нем запускается Shell. Смотрите эту функцию: https://developer.gnome.org/vte/unstable/VteTerminal.html#vte-terminal-spawn-async. Это — VTE widget, созданный и поддерживаемый GNOME. В нем и происходит почти вся работа по созданию терминалов. Конкретно в данной функции 4 аргументом принимается нужная команда, создается PTY и в новом процессе запускается данная команда на созданном PTY.
Посмотрел.
- /dev/ptmx — это все таки устройство. Фраза — "это не устройство, а интерфейс" странная, так как данное и является интерфейсом для создания pty. Как это работает? Мы вызываем open(/dev/ptmx), и вызов open обслуживает драйвер данного устройства, конкретнее мы видели, что за это отвечает функция
ptmx_open
. - "PTM и PTS — это виртуальные устройства...". Да, это верно, но не по той причине что вы написали, а потому, что они не существуют физически на диске, а живут в виртуальной файловой системе /dev, т.е. живут в памяти, в ядре. Вообще, то, как я определил виртуальные устройства — расходится с тем, что говорит википедия. Там виртуальные устройства — это устройства, не взаимодействующие напрямую с аппаратными устройствами. Так что лучше избегать понятия "виртуальное устройство" по отношению к ptm/pts и говорить, что PTM и PTS являются файлами устройств, а конкретнее, терминальными устройствами. Не думаю, что их можно назвать виртуальными устройствами, так как формально они взаимодействуют с терминалом. Вот /dev/null уже является виртуальным устройством.
- Ну и последнее я считаю своей самой большой ошибкой в статье. Зря я вообще заикнулся о gnome терминале. Дело в том, что его работа намного сложнее, чем какой-нибудь xterm. Он не создает новые процессы для терминалов, а запускает их внутри тредов. Программы внутри терминала конечно же запускаются в отдельных процессах (а конкретнее этим занимается vte widget и его функция vte_terminal_spawn_async). Мой вам совет — поизучайте xterm — крайне простой и понятный эмулятор терминала, который, более того, работает в обход gtk, gnome и всяких других графических тулкитов.
Если вам интересно, убедиться в том, что gnome терминал — не отдельный процесс, можно достаточно просто. Введите:
$ ps --pid $$ --format ppid=
И вы увидите, что родителем баша является сам Gnome Terminal Server. Да, это кажется странным со стороны, но наверняка на то были причины, что gnome терминалы работают внутри тредов. Первую причину, которую я вижу, это функциональность вкладок (tabs).
Пишите в лс, можем еще что-то обсудить, если понятнее не стало :)
Хотя насчет простоты xterm я все таки погорячился — его соурс код сложно понятен, да и вообще сам он раздут сильно по возможностям и наполнен многими ненужными в актуальное время вещами. Но в качестве понимания того, как примерно эмулятор терминала работает, вполне пойдет
Рекомендую st для более глубого изучения устройства терминалов — это точно самый простой и понятной терминал на сегодня. https://st.suckless.org/
Hello, World! Глубокое погружение в Терминалы