Jak oszukać polecenie, by pomyślało, że jego wyjście trafia do terminala


38

Biorąc pod uwagę polecenie, które zmienia swoje zachowanie, gdy jego dane wyjściowe trafiają do terminala (np. Produkują kolorowe dane wyjściowe), jak można przekierować dane wyjściowe w potoku, zachowując zmienione zachowanie? Musi być na to narzędzie, którego nie jestem świadomy.

Niektóre polecenia, na przykład grep --color=always, mają flagi opcji, które wymuszają zachowanie, ale pytanie brzmi, jak obejść programy, które polegają wyłącznie na testowaniu deskryptora pliku wyjściowego.

Jeśli to ma znaczenie, moja powłoka jest bashw systemie Linux.


Musisz wiedzieć, w jaki sposób polecenie testuje deskryptor pliku wyjściowego i jakoś zwraca wyniki zgodne z wynikami, które można zobaczyć z terminala wyjściowego.
Andrew Henle,

Odpowiedzi:


21

Możesz uzyskać to, czego potrzebujesz, używając unbuffer.

unbufferto tcl/ expectskrypt. Spójrz na źródło, jeśli chcesz. Zwróć również uwagę na sekcję OSTRZEŻENIA u mężczyzny.

Należy również pamiętać, że nie wykonuje aliasów takich jak:

alias ls='ls --color=auto'

chyba że ktoś doda lewę, jak zauważył Stéphane Chazelas:

Jeśli zrobisz alias unbuffer='unbuffer '(zwróć uwagę na spację końcową), aliasy zostaną rozwinięte po unbuffer.


Uwaga na potwierdzone aliasy - nie będzie również działać z innymi konstrukcjami powłoki, takimi jak wbudowane funkcje.
Amir

4
Jeśli zrobisz alias unbuffer='unbuffer '(zwróć uwagę na spację końcową), aliasy zostaną rozwinięte po unbuffer.
Stéphane Chazelas

unbufferto jest! sudo apt install expect- To było niejasne.
loxaxs

22

Historia zestawów narzędzi

Nie jesteś pierwszą osobą, która chce takiego narzędzia. Ludzie chcą takich narzędzi od 30 lat. I istnieją też prawie tak długo.

Najwcześniejszym narzędziem do tego rodzaju rzeczy był pakiet „pty” Daniela J. Bernsteina, opisany przez Richa Salz'a jako „nóż Ginsu”, który Bernstein napisał na przełomie lat 90. XX wieku, aby oszukiwać w nethacku (sic!). Wersja 4 pakietu „pty” została opublikowana w 1992 r. Do comp.sources.unix(tom 25, numery 127–135). Nadal można go zlokalizować w sieci WWW. Paul Vixie opisał to wtedy:

Co mogę powiedzieć? Kroi, kroi, myje naczynia, wyprowadza psa. „Po prostu działa”, co oznacza, że ​​postępując zgodnie ze wskazówkami, otrzymasz pakiet roboczy bez ciągnięcia włosów lub zgrzytania zębami lub innych standardowych czynności przenoszenia.

Bernstein później zaktualizował to, gdzieś w dniu 1999-04-07 lub wcześniej, o pakiet „ptyget”, który ogłosił:

Stworzyłem nowy pseudo-tty alokator, ptyget. Wersja alfa jest na ftp://koobera.math.uic.edu/pub/software/ptyget-0.50.tar.gz. Istnieje lista mailingowa ptyget; aby dołączyć, wyślij pustą wiadomość na adres djb-ptyget-requ...@koobera.math.uic.edu. Interfejs ptyget zaprojektowałem od zera. Jest o wiele bardziej modułowy niż pty; podstawowy interfejs pty został teraz podzielony na trzy części:

  • ptyget: niewielki program niskiego poziomu - jedyny program setuid w pakiecie - który przydziela nowy pseudo-tty i przekazuje go do wybranego programu
  • ptyspawn: inny mały program, który uruchamia proces potomny pod pseudo-tty, czekając na jego zakończenie i obserwując zatrzymania
  • ptyio: inny, tylko nieco większy, program, który przenosi dane tam iz powrotem

Stary nóż Ginsu ptyjest teraz ortograficzny ptybandage, co jest synonimem ptyget ptyio -t ptyspawn; pty -d, do dołączania programów sieciowych do pseudo-ttys, jest teraz pisownia ptyrun, co jest synonimem ptyget ptyio ptyspawn; i nobufjest synonimem ptyget ptyio -r ptyspawn -23x. Podzieliłem funkcje zarządzania sesjami na osobny pakiet.

Ten oddzielny pakiet był pakietem „sess”.

Nawiasem mówiąc, „ptyget” jest godnym uwagi przykładem bardzo wczesnej wersji i jednego z niewielu opublikowanych przypadków własnego, niepublikowanego systemu kompilacji „przerobić” Bersteina. dependonjest wyraźnym prekursorem redo-ifchange.

Stosowanie

ptybandage

ptybandageto jest to, czego ludzie zwykle chcą podczas sesji logowania. Jego podstawowym zastosowaniem jest tworzenie programów, które są wrażliwe na to, czy ich standardowe dane wejściowe, wyjściowe lub błędy są podłączone do terminali, działają w ten sposób, nawet jeśli faktycznie znajdują się w potokach powłoki, lub ich standardowe deskryptory plików są przekierowywane do pliku.

Zajmuje polecenia do uruchomienia (który musi być właściwa komenda zewnętrzny, oczywiście) i uruchamia go w taki sposób, że uważa, że jego standardowe wejście, wyjście i błąd są dołączone do terminala, podłączenie tych aż do ptybandage„s oryginalne standardowe wejście, wyjście i błąd.

Zajmuje się niuansami działania pod powłokami kontroli zadań, zapewniając, że znak STOP terminala nie tylko zatrzymuje się, ptybandageale także zatrzymuje działanie programu podłączonego do wewnętrznego terminalu.

ptyrun

ptyrunto jest to, czego ludzie zwykle chcą na serwerach sieciowych TCP. Jego podstawowym zastosowaniem są środowiska zdalnego wykonywania, które same nie skonfigurowały terminali, uruchamiając programy, które nie działają zgodnie z oczekiwaniami, gdy nie ma terminala.

Nie oczekuje się, że będzie działał pod powłoką kontroli zadania, a jeśli uruchamiane polecenie otrzyma sygnał zatrzymania, zostanie po prostu ponownie uruchomiony.

Dostępne zestawy narzędzi

Dru Nelson publikuje zarówno wersję „pty” 4, jak i „ptyget”.

Paul Jarc publikuje poprawioną wersję ptyget, która próbuje poradzić sobie z ioctlami pseudoterminalnymi specyficznymi dla systemu operacyjnego w oryginale, których systemy operacyjne w rzeczywistości nie zapewniają.

Pakiet źródłowy nosh zawiera podobne do niego skrypty ptybandangei ptyrunskrypty, które używają execlinenarzędzia Laurenta Bercot'a oraz własnych pseudoterminalnych poleceń zarządzania pakietem nosh. Od wersji 1.23 nosh są one dostępne w pakiecie z pakietem dodatków terminal-nosh. (Wcześniejsze wersje dostarczały je tylko osobom, które budowały ze źródła).

Kilka przykładów zastosowań

Jurjgen Oskam używa ptybandagew systemie AIX do wprowadzania danych wejściowych z dokumentu tutaj do programu, który otwiera explicity, i odczytuje terminal sterujący w celu wyświetlenia hasła:

$ ptybandage dsmadmc << EOF> uit.txt
joskam
hasło
sesja zapytań
proces zapytania
porzucić
EOF

Andy Bradford używa ptyrunna OpenBSD pod daemontools i ucspi-tcp, aby program bgplgshinteraktywnego sterowania routerem był dostępny przez sieć, jednocześnie myśląc, że rozmawia z terminalem:

#! / bin / sh
exec 2> i 1
exec envuidgid rviews tcpserver -vDRHl0 0 23 ptyrun / usr / bin / bgplgsh

Dalsza lektura


Dzięki za lekcję historii, ale narzędzia, które sugerujesz, nie są dostępne w nowoczesnej dystrybucji Linuksa, a zatem nie są przydatne.
Amir,

4
Istnieje kilka hiperłączy i cała sekcja odpowiedzi poświęcona tym, gdzie narzędzia zdecydowanie dostępne.
JdeBP,

1
Jaka jest twoja opinia expect?
CMCDragonkai

20

Możesz użyć socat, aby rozpocząć proces z podłączonym pty i uzyskać od socat połączenie drugiego końca pty z plikiem. Które AFAIU jest dokładnie tym, o co prosiłeś:

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

Ta metoda spowoduje, że isattywywoływany przez my-commandreturn, truea proces, który opiera się tylko na tym, zostanie oszukany do wyjściowych kodów sterujących. Zauważ, że niektóre procesy (zwłaszcza grep) również sprawdzają wartość TERMzmiennej środowiskowej, więc może być konieczne ustawienie jej na coś rozsądnego, na przykład"xterm"


13

Jest też dobre rozwiązanie zamieszczone tutaj na Super User przez KarlC :

Skompiluj małą bibliotekę współdzieloną:

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

Następnie powiedz swojemu poleceniu, aby isatty(3)dynamicznie ładowało to zastąpienie:

LD_PRELOAD=./isatty.so mycommand

Może to nie działać w przypadku każdego polecenia, może nawet złamać niektóre w nieoczekiwany sposób, ale prawdopodobnie zadziałałoby w większości przypadków.


2
Użytkownicy systemu MacOS mogą uzyskać to samo zachowanie, używającDYLD_INSERT_LIBRARIES=./isatty.so DYLD_FORCE_FLAT_NAMESPACE=y mycommand
Christopher Shroba

12

Co powiesz na używanie script(1)?

Na przykład:

script -q -c 'ls -G' out_file

Zapisuje dane lswyjściowe out_filez zachowanymi kodami kolorów.


To nie działa tutaj. Jak zachowane są kolory? Czy jest jakieś narzędzie, którego powinienem używać do generowania out_filekolorów?
Kira

1
@Kira używam do przeglądania plików z sekwencjami zmiany koloru ANSI less -R. Jednak w tym przypadku chciałem, aby dane wyjściowe były kontynuowane w potoku, co ostatecznie zakończyło się w moim terminalu. Używając catilustracji, było to coś w rodzaju script -q -c 'ls -G' /dev/null | cat, co typescriptcałkowicie pomija plik, pozostawiając jedynie wyjście programu.
Amir

Aby uniknąć tworzenia pliku, po prostu użyj myślnika ( -) jako scriptpliku wyjściowego, na przykład:script -q -c 'ls -G' -
Franklin Piat,

0

W oparciu o odpowiedź @ Amir , oto skrypt, który generuje, a następnie dołącza bibliotekę w czasie wykonywania:

#!/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" "$@"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.