Як обманути команду на думку, що її вихід збирається до терміналу


38

З огляду на команду, яка змінює свою поведінку, коли її вихід збирається до терміналу (наприклад, виробляє кольоровий вихід), як можна цей результат перенаправляти в конвеєр, зберігаючи змінену поведінку? Для цього повинна бути утиліта, про яку я не знаю.

Деякі команди, наприклад grep --color=always, мають прапорці опцій, щоб змусити поведінку, але питання полягає в тому, як обійти програми, які покладаються виключно на тестування дескриптора вихідного файлу.

Якщо це має значення, моя оболонка знаходиться bashв Linux.


Ви повинні знати, як команда тестує свій дескриптор вихідного файлу і якось повертає результати, що відповідають результатам, які видно з терміналу виводу.
Ендрю Генле

Відповіді:


21

Ви можете отримати те, що вам потрібно, використовуючи unbuffer.

unbufferє tcl/ expectсценарій. Подивіться на джерело, якщо хочете. Також зверніть увагу на розділ КАВІТИ в людині.

Також зауважте, що він не виконує псевдоніми, такі як:

alias ls='ls --color=auto'

якщо тільки не додати хитрість, як зазначив Стефан Шазелас:

Якщо ви зробите alias unbuffer='unbuffer '(відзначте пробіл), то псевдоніми будуть розширені після unbuffer.


Зверніть увагу на визнані псевдоніми - вони також не працюватимуть з будь-якими іншими конструкціями оболонок, такими як вбудовані та функції.
Амір

4
Якщо ви зробите alias unbuffer='unbuffer '(відзначте пробіл), то псевдоніми будуть розширені після unbuffer.
Стефан Шазелас

unbufferЦе є! sudo apt install expect- Це було незрозуміло.
loxaxs

22

Історія наборів інструментів

Ви не перша людина, яка захотіла такого інструменту. Люди хочуть таких інструментів вже 30 років. І вони існували майже так само довго.

Найбільш раннім інструментом для подібних речей був пакет «pty» Даніеля Дж. Бернштейна, який Річ Зальц описав як «ніж Гінсу», який Бернштейн написав ще на рубежі 90-х, щоб обдурити шахрайство (sic!). Версія 4 пакету "pty" була опублікована в 1992 р. comp.sources.unix(Том 25 випусків 127 - 135). Він все ще розміщений у всесвітній павутині. Пол Віксі описав це в той час:

Що я можу сказати? Це скибочки, воно кубики, миє посуд, вона гуляє собаку. Це "просто працює", це означає, що якщо ви будете дотримуватися вказівок, ви отримаєте робочий пакет без витягування волосся, скреготування зубів або інших стандартних заходів з перенесення.

Пізніше Бернштейн оновив це, колись або перед 1999-04-07, пакетом "ptyget", який він оголосив:

Я зібрав новий розподільник псевдо-тти, ptyget. Альфа-версія є на ftp://koobera.math.uic.edu/pub/software/ptyget-0.50.tar.gz. Є список розсилки ptyget; приєднатися, надіслати порожнє повідомлення djb-ptyget-requ...@koobera.math.uic.edu. Я розробив інтерфейс ptyget з нуля. Це набагато модульніше, ніж pty; базовий інтерфейс pty тепер розділений на три частини:

  • ptyget: крихітна програма низького рівня - єдина в програмі встановлена ​​програма - яка виділяє нову псевдо-tty та передає її програмі на ваш вибір
  • ptyspawn: ще одна невелика програма, яка запускає дочірній процес під псевдо-tty, очікуючи його виходу та спостерігає за зупинками
  • ptyio: інша, лише трохи більша програма, яка переміщує дані вперед і назад

Старий ніж Гінсу ptyтепер написаний ptybandage, що є синонімом ptyget ptyio -t ptyspawn; pty -d, для приєднання мережевих програм до псевдо-ttys тепер написано ptyrun, що є синонімом ptyget ptyio ptyspawn; і nobufє синонімом для ptyget ptyio -r ptyspawn -23x. Я розділив функції управління сеансами на окремий пакет.

Цей окремий пакет був пакетом "sess".

"Ptyget", до речі, примітний тим, що є прикладом дуже ранньої версії, і одним з небагатьох опублікованих примірників власної ніколи не опублікованої системи "повторної" побудови Берштейна. dependonє явним попередником для redo-ifchange.

Використання

ptybandage

ptybandageце те, що люди зазвичай хочуть під час сеансу входу. Його основним випадком використання є створення програм, які чутливі до того, чи їх стандартні входи, виходи або помилки підключені до терміналів, таким чином функціонують, навіть якщо вони насправді знаходяться в оболонкових трубопроводах, або їх стандартні дескриптори файлів перенаправлені до файлу.

Він виконує команду для запуску (яка, звичайно, повинна бути належною зовнішньою командою) і виконує її таким чином, що він думає, що її стандартний вхід, вихід та помилка приєднані до терміналу, підключаючи їх через ptybandage s оригінальний стандарт введення, виводу та помилки.

Він стосується нюансів роботи під оболонками управління роботою, гарантуючи, що символ STOP терміналу не тільки зупиняється, ptybandageале й зупиняє роботу програми, прикріплену до внутрішнього терміналу.

ptyrun

ptyrunце те, що люди зазвичай хочуть на мережевих серверах TCP. Його основним випадком використання є середовища віддаленого виконання, які самі не встановили термінали, запускаючи програми, які не працюють так, як потрібно, коли немає терміналу.

Він не очікує, що він буде запущений під оболонкою управління завданням, і якщо команда, що виконується, отримує сигнал зупинки, вона просто перезапускається.

Доступні набори інструментів

Дру Нельсон публікує "pty" версії 4 та "ptyget".

Пол Jarc публікує фіксовану версію ptyget, що намагається розібратися з специфічними для операційної системи псевдо-кінцевими пристроями ioctls в оригіналі, який операційні системи насправді більше не надають.

Пакет джерела nosh поставляється з діючими ptybandangeта ptyrunскриптами, які використовують execlineінструмент Лорана Беркота та власні команди управління псевдотермінальними пакетами nosh. З нош-версії 1,23 вони доступні заздалегідь упаковані в пакет nosh-terminal-extras. (Раніші версії постачали їх лише людям, які будували з джерела.)

Кілька прикладів використання

Юріген Оскам, використовуючи ptybandageAIX щоб подати вхід з документа тут у програму, яка відкриває explicity та читає її керуючий термінал для запиту пароля:

$ ptybandage dsmadmc << EOF> uit.txt
джоскам
пароль
сеанс запитів
процес запиту
кинути
EOF

Енді Бредфорд, використовуючи ptyrunOpenBSD під daemontools та ucspi-tcp, щоб зробити bgplgshінтерактивну програму управління маршрутизатором доступною через мережу, в той час як змусив її думати, що він спілкується з терміналом:

#! / бін / ш
exec 2> & 1
exec envuidgid rviews tcpserver -vDRHl0 0 23 ptyrun / usr / bin / bgplgsh

Подальше читання


Дякуємо за урок історії, але запропоновані вами інструменти недоступні в сучасному дистрибутиві Linux, отже, не корисні.
Амір

4
Існує купа гіперпосилань та цілий розділ відповіді, присвячений тому, де інструменти, безумовно , доступні.
JdeBP

1
Яка ваша думка expect?
CMCDragonkai

20

Ви можете використовувати socat, щоб розпочати процес із підключеним pty , і отримати socat для підключення другого кінця pty до файлу. Який саме AFAIU саме те, про що ви запитували

socat EXEC:"my-command",pty GOPEN:mylog.log

Цей метод призведе до isattyвиклику my-commandповернення, trueі процес, який покладається лише на це, буде обдурений на вихідні коди управління. Зауважте, що деякі процеси (зокрема grep) також перевіряють значення TERMзмінної середовища, тому вам може знадобитися встановити це на щось розумне, наприклад"xterm"


13

Також є приємне рішення, розміщене тут на Super User від KarlC :

Складіть невелику спільну бібліотеку:

echo "int isatty(int fd) { return 1; }" | gcc -O2 -fpic -shared -ldl -o isatty.so -xc -

Потім скажіть вашій команді isatty(3)динамічно завантажувати цю переопрацювання:

LD_PRELOAD=./isatty.so mycommand

Це може не працювати для кожної команди там, може навіть порушити деякі несподівані способи, але, мабуть, спрацює в більшості випадків.


2
Для користувачів MacOS ви можете отримати таку саму поведінку, скориставшисьDYLD_INSERT_LIBRARIES=./isatty.so DYLD_FORCE_FLAT_NAMESPACE=y mycommand
Крістофер Шроба

12

Як щодо використання script(1)?

Наприклад:

script -q -c 'ls -G' out_file

Збереже lsвисновок до out_fileзбережених кольорових кодів.


Тут це не працює. Як зберігаються кольори? Чи є інструмент, який я повинен використовувати для виведення out_fileйого кольорами?
Кіра

1
@Kira для перегляду файлів із послідовностями кольорового відтворення ANSI, я використовую less -R. Однак у цьому випадку я хотів, щоб результат продовжувався в конвеєрі, який в кінцевому підсумку виявився в моєму терміналі. Використовуючи catдля ілюстрації, це було щось на зразок script -q -c 'ls -G' /dev/null | cat, що typescriptповністю придушує файл, залишаючи лише вихід програми.
Амір

Щоб уникнути створення файлу, просто використовуйте тире ( -) як scriptвихідний файл, наприклад:script -q -c 'ls -G' -
Franklin Piat

0

На основі відповіді @ Amir , ось сценарій, який створює, а потім включає бібліотеку під час виконання:

#!/bin/bash
set -euo pipefail

function clean_up {
  trap - EXIT # Restore default handler to avoid recursion
  [[ -e "${isatty_so:-}" ]] && rm "$isatty_so"
}
# shellcheck disable=2154 ## err is referenced but not assigned
trap 'err=$?; clean_up; exit $err' EXIT HUP INT TERM

isatty_so=$(mktemp --tmpdir "$(basename "$0")".XXXXX.isatty.so)
echo "int isatty(int fd) { return 1; }" \
  | gcc -O2 -fpic -shared -ldl -o "$isatty_so" -xc -
# Allow user to SH=/bin/zsh faketty mycommand
"${SH:-$SHELL}" -c 'eval $@' - LD_PRELOAD="$isatty_so" "$@"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.