Ik probeer het tegenovergestelde te doen van “Detecteren of stdin een terminal of pijp is?“.
Ik gebruik een toepassing die het uitvoerformaat verandert omdat het een pijp op STDOUT detecteert, en ik wil dat het denkt dat het een interactieve terminal is, zodat ik dezelfde uitvoer krijg bij het omleiden.
Ik dacht dat het inpakken in een expect
-script of het gebruik van een proc_open()
in PHP het zou doen, maar dat doet het niet.
Heeft u ideeën?
Antwoord 1, autoriteit 100%
Aha!
De opdracht script
doet wat we willen…
script --return --quiet -c "[executable string]" /dev/null
Zou het lukken!
Usage:
script [options] [file]
Make a typescript of a terminal session.
Options:
-a, --append append the output
-c, --command <command> run command rather than interactive shell
-e, --return return exit code of the child process
-f, --flush run flush after each write
--force use output file even when it is a link
-q, --quiet be quiet
-t[<file>], --timing[=<file>] output timing data to stderr or to FILE
-h, --help display this help
-V, --version display version
Antwoord 2, autoriteit 39%
Op basis van Chris’ oplossingheb ik de volgende kleine hulpfunctie bedacht:
faketty() {
script -qfc "$(printf "%q " "$@")" /dev/null
}
De eigenzinnig uitziende printf
is nodig om de argumenten van het script correct uit te breiden in $@
terwijl mogelijk geciteerde delen van de opdracht worden beschermd (zie voorbeeld hieronder).
Gebruik:
faketty <command> <args>
Voorbeeld:
$ python -c "import sys; print sys.stdout.isatty()"
True
$ python -c "import sys; print sys.stdout.isatty()" | cat
False
$ faketty python -c "import sys; print sys.stdout.isatty()" | cat
True
Antwoord 3, autoriteit 15%
Het unbuffer-script dat wordt geleverd met Verwachtzoudit goed moeten afhandelen. Als dat niet het geval is, kijkt de toepassing mogelijk naar iets anders dan waar de uitvoer op is aangesloten, bijv. waarop de omgevingsvariabele TERM is ingesteld.
Antwoord 4, autoriteit 11%
Verwijzend naar het vorige antwoord, op Mac OS X, kan “script” worden gebruikt zoals hieronder…
script -q /dev/null commands...
Maar omdat het “\n” kan vervangen door “\r\n” op de stdout, heb je misschien ook een script als dit nodig:
script -q /dev/null commands... | perl -pe 's/\r\n/\n/g'
Als er een pijp tussen deze commando’s zit, moet je stdout doorspoelen. bijvoorbeeld:
script -q /dev/null commands... | ruby -ne 'print "....\n";STDOUT.flush' | perl -pe 's/\r\n/\n/g'
Antwoord 5, autoriteit 10%
Ik weet niet of het mogelijk is vanuit PHP, maar als je het onderliggende proces echt nodig hebt om een TTY te zien, kun je een PTY.
In C:
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <unistd.h>
#include <pty.h>
int main(int argc, char **argv) {
int master;
struct winsize win = {
.ws_col = 80, .ws_row = 24,
.ws_xpixel = 480, .ws_ypixel = 192,
};
pid_t child;
if (argc < 2) {
printf("Usage: %s cmd [args...]\n", argv[0]);
exit(EX_USAGE);
}
child = forkpty(&master, NULL, NULL, &win);
if (child == -1) {
perror("forkpty failed");
exit(EX_OSERR);
}
if (child == 0) {
execvp(argv[1], argv + 1);
perror("exec failed");
exit(EX_OSERR);
}
/* now the child is attached to a real pseudo-TTY instead of a pipe,
* while the parent can use "master" much like a normal pipe */
}
Ik had eigenlijk de indruk dat expect
zelf maakt echter een PTY aan.
Antwoord 6, autoriteit 7%
Het antwoord van @A-Ron op . bijwerken
a) werken op zowel Linux & MacOs
b) indirecte statuscode verspreiden (aangezien MacOs script
dit niet ondersteunt)
faketty () {
# Create a temporary file for storing the status code
tmp=$(mktemp)
# Ensure it worked or fail with status 99
[ "$tmp" ] || return 99
# Produce a script that runs the command provided to faketty as
# arguments and stores the status code in the temporary file
cmd="$(printf '%q ' "$@")"'; echo $? > '$tmp
# Run the script through /bin/sh with fake tty
if [ "$(uname)" = "Darwin" ]; then
# MacOS
script -Fq /dev/null /bin/sh -c "$cmd"
else
script -qfc "/bin/sh -c $(printf "%q " "$cmd")" /dev/null
fi
# Ensure that the status code was written to the temporary file or
# fail with status 99
[ -s $tmp ] || return 99
# Collect the status code from the temporary file
err=$(cat $tmp)
# Remove the temporary file
rm -f $tmp
# Return the status code
return $err
}
Voorbeelden:
$ faketty false ; echo $?
1
$ faketty echo '$HOME' ; echo $?
$HOME
0
embedded_example () {
faketty perl -e 'sleep(5); print "Hello world\n"; exit(3);' > LOGFILE 2>&1 </dev/null &
pid=$!
# do something else
echo 0..
sleep 2
echo 2..
echo wait
wait $pid
status=$?
cat LOGFILE
echo Exit status: $status
}
$ embedded_example
0..
2..
wait
Hello world
Exit status: 3
Antwoord 7, autoriteit 5%
Te nieuw om commentaar te geven op het specifieke antwoord, maar ik dacht dat ik de functie faketty
zou opvolgen die hierboven door ingomueller-net is gepost, aangezien het me onlangs heeft geholpen.
Ik ontdekte dat dit een typescript
-bestand aan het maken was dat ik niet wilde/nodig had, dus voegde ik /dev/null toe als het scriptdoelbestand:
function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }
Antwoord 8, autoriteit 2%
Er is ook een pty-programma opgenomen in de voorbeeldcode van het boek “Advanced Programming in the UNIX Environment, Second Edition”!
Zo compileert u pty op Mac OS X:
man 4 pty # pty -- pseudo terminal driver
open http://en.wikipedia.org/wiki/Pseudo_terminal
# Advanced Programming in the UNIX Environment, Second Edition
open http://www.apuebook.com
cd ~/Desktop
curl -L -O http://www.apuebook.com/src.tar.gz
tar -xzf src.tar.gz
cd apue.2e
wkdir="${HOME}/Desktop/apue.2e"
sed -E -i "" "s|^WKDIR=.*|WKDIR=${wkdir}|" ~/Desktop/apue.2e/Make.defines.macos
echo '#undef _POSIX_C_SOURCE' >> ~/Desktop/apue.2e/include/apue.h
str='#include <sys/select.h>'
printf '%s\n' H 1i "$str" . wq | ed -s calld/loop.c
str='
#undef _POSIX_C_SOURCE
#include <sys/types.h>
'
printf '%s\n' H 1i "$str" . wq | ed -s file/devrdev.c
str='
#include <sys/signal.h>
#include <sys/ioctl.h>
'
printf '%s\n' H 1i "$str" . wq | ed -s termios/winch.c
make
~/Desktop/apue.2e/pty/pty ls -ld *
Antwoord 9, autoriteit 2%
Ik probeerde kleuren te krijgen bij het uitvoeren van shellcheck <file> | less
op Linux, dus ik heb de bovenstaande antwoorden geprobeerd, maar ze produceren dit bizarreffect waarbij tekst horizontaal wordt gecompenseerd vanwaar het zou moeten zijn:
In ./all/update.sh line 6:
for repo in $(cat repos); do
^-- SC2013: To read lines rather than words, pipe/redirect to a 'while read' loop.
(Voor degenen die niet bekend zijn met ShellCheck, wordt de regel met de waarschuwing verondersteld op te staan met het waar het probleem is.)
Voor de bovenstaande antwoorden om met ShellCheck te werken, probeerde ik een van de opties uit de opmerkingen:
faketty() {
0</dev/null script -qfc "$(printf "%q " "$@")" /dev/null
}
deze werkt. Ik heb ook --return
en gebruikte lange opties om deze opdracht een beetje minder ondoorgrondelijk te maken:
faketty() {
0</dev/null script --quiet --flush --return --command "$(printf "%q " "$@")" /dev/null
}
Werkt in Bash en ZSH.