Как подключить клавиатуру и именованный канал к STDIN в Bash? - PullRequest
3 голосов
/ 25 ноября 2010

Я пытаюсь найти способ вызвать интерактивную программу командной строки, чтобы она принимала ввод как непосредственно с клавиатуры, так и из именованного канала. Моя цель - заставить это работать с MATLAB, но я думаю, что Bash работает так же, как пример. Поэтому идея состоит в том, чтобы запустить Bash, и после его запуска я могу набирать команды, использовать стрелку вверх для истории и т. Д., А также отправлять команды в именованный канал. Я несколько дней оглядывался по сторонам и возился с этим, но пока ничего из того, что я пробовал, не сработало.

Например, на https://serverfault.com/questions/171095/how-do-i-join-two-named-pipes-into-single-input-stream-in-linux есть полезная ветка, которая предлагает сделать что-то вроде этого:

mkfifo alt_in
(tail -f alt_in & cat) | bash

Это почти то, что я ищу, за исключением того, что, если вы попытаетесь использовать клавиши Backspace или клавиши со стрелками, это не будет работать правильно. (Я полагаю, это потому, что cat перехватывает нажатия клавиш, которые обычно обрабатываются библиотекой readline в bash?) У кого-нибудь есть другие предложения?

В конечном итоге я хотел бы иметь способ запустить процесс MATLAB, чтобы я мог отправлять ему команды из TextMate, но также взаимодействовать с ним в терминале. Я использую MATLAB для работы, но я не большой поклонник его GUI или редактора.

Изменить 19 декабря 2010 г.

Спасибо за все очень полезные предложения! Я хотел бы подвести итог этого для всех, кто заинтересован. Я посмотрел на rlwrap, но так как моя цель состояла в том, чтобы заставить это работать внутри пакета TextMate, который любой мог использовать, я не решался положиться на нестандартную утилиту (которую я должен был упомянуть в первую очередь). Я также кратко проверил expect и unbuffer, но они кажутся довольно сложными, и у меня просто не хватило смелости погрузиться в это.

screen работал довольно хорошо для этого - как предложено ниже, я мог бы открыть Терминал, запустить screen, запустить matlab -nodesktop, и затем было возможно, чтобы TextMate, например, отправлял выбранный текст в Matlab, используя screen -X ... внутри команды TextMate. Недостатки этого подхода, которые я заметил, были:

  1. Отправка блока текста, содержащего более 1024 символов, привела к ошибке из `screen`; Я полагаю, что где-то есть какой-то буфер, который не может вместить больше этого, но не тратит время на его поиск.
  2. Экран имеет собственный буфер прокрутки, что делает полосу прокрутки в терминале довольно бесполезной. Может быть, есть возможность изменить, как это работает?
  3. Control-A - это комбинация клавиш `экрана`; Вы не можете использовать его для перехода к началу строки, если не перепутали командную клавишу.

Пока я играл с screen, мне пришло в голову, что, хотя вопрос, который я задал, касается соединения каналов, STDIN и т. Д., Я на самом деле забочусь об этом только для очень конкретного случая: получения текста из TextMate для Терминал. И это побудило меня попробовать сделать это с AppleScript, и удивительно, что оказалось проще и надежнее, чем любая другая вещь, которую я пробовал. Создайте команду TextMate, которая принимает выбранный текст или текущую строку в качестве ввода и содержит

#!/usr/bin/env osascript

set input_command to do shell script "cat"

tell application "Terminal"
    do script input_command in window 1
end tell

И это прекрасно работает, пока MATLAB находится в самом переднем окне терминала. (Также возможно выполнить поиск вкладки «Терминал», на которой выполняется MATLAB, я просто исключил это для ясности.)

Мораль этой истории в том, что я должен задавать более конкретные вопросы. Еще раз спасибо всем за помощь; Я многому научился в борьбе с этим!

Ответы [ 3 ]

2 голосов
/ 25 ноября 2010

Попробуйте:

mkfifo alt_in
(tail -f alt_in & rlwrap cat) | bash

Вы не получите приглашение, но вы можете вводить команды и использовать клавиши со стрелками и т. Д., Включая извлечение истории.Вы можете echo команды из другого терминала в именованный канал, и они будут выполняться на принимающей стороне, но они не будут в его истории.

Некоторые другие вещи для исследования:

  • ожидаем
  • screen -x и screen -X

Для последнего в одном терминале запускается screen.Там вы сможете взаимодействовать с Bash почти так же, как обычно.Теперь на другом терминале выполните

screen -ls

, чтобы определить PID сеанса screen, который вы начали.Это будут цифры в начале строки, которая выглядит следующим образом:

31544.pts-2.hostname     (01/01/2010 01:01:01 PM)        (Attached)

Теперь вы можете делать такие вещи:

screen -S 31544 -X stuff $'echo Your ad here.\n'

, что приведет к команде echoбыть выполненным на другом терминале.$'' вызывает интерпретацию escape-последовательностей внутри, в этом случае мы получаем новую строку, чтобы мы могли «нажать» Enter .

Допустим, мы сделали это:

screen -S 31544 -X stuff $'top\n'

Сейчас top запущен.Мы могли бы пойти к этому терминалу и нажать q , чтобы выйти, но где в этом веселье?

screen -S 31544 -X stuff 'q'

Обратите внимание, на этот раз нам не нужен перевод строки.

1 голос
/ 25 ноября 2010

Попробуйте передать данные в bash через unbuffer.

0 голосов
/ 25 ноября 2010

Ввод с клавиатуры осуществляется в разных вариантах, называемых «сырой режим», «режим разбивки» и «режим приготовления».

Необработанный режим - это когда ОС передает каждое нажатие клавиши, когда вы вводите его в программу (например, bash).

Режим приготовления - это когда операционная система буферизует строку и позволяет выполнять простое редактирование, например удаление символов. Когда вы нажимаете RETURN или EOF (обычно Ctrl-D ), он отправляет строку в программу.

Команда stty позволяет вам определить количество кодов клавиш, которые интерпретируются как конец строки (RETURN), EOF (Ctrl-D) и множество других.

Cbreak-mode - это промежуточный пункт, в котором многие управляющие символы сохраняют свои обычные функции, но ОС по-прежнему отправляет символы по одному в приложение. Такие программы, как bash, vi и менее, обычно используют этот режим.

Если вы переведете свой терминал в режим raw, то вы больше не сможете использовать свою клавиатуру, чтобы «сломать» его, если не работает программа, с которой вы работаете.

Ожидайте ( здесь или здесь ) может представить интерфейс терминала для Bash, чтобы он по-прежнему считал, что работает с обычной клавиатуры и будет выполнять всю классную командную строку bash редактирование, к которому мы привыкли.

И Expect может читать ввод с клавиатуры в необработанном режиме и по каналу и без проблем передавать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...