J'essaie de faire le contraire de
Détecter si stdin est un terminal ou un tuyau?
J'exécute une application qui change son format de sortie car elle détecte un canal sur stdout, et je veux qu'elle pense que c'est un terminal interactif pour que j'obtienne la même sortie lors de la redirection.
Je pensais que l'envelopper dans un script expect
ou utiliser une proc_open()
dans PHP le ferait, mais ce n'est pas le cas.
Des idées?
Aha!
La commande script
fait ce que nous voulons ...
script --return --quiet -c "[executable string]" /dev/null
Fait l'affaire!
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
Basé sur solution de Chris , j'ai trouvé la petite fonction d'aide suivante:
faketty() {
script -qfc "$(printf "%q " "$@")" /dev/null
}
L'aspect bizarre printf
est nécessaire pour développer correctement les arguments du script dans $@
tout en protégeant les parties éventuellement citées de la commande (voir l'exemple ci-dessous).
Utilisation:
faketty <command> <args>
Exemple:
$ 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
Je ne sais pas si c'est faisable depuis PHP, mais si vous avez vraiment besoin du processus enfant pour voir un TTY, vous pouvez créer un PTY .
En 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 */
}
J'avais en fait l'impression que expect
lui-même crée un PTY, cependant.
En se référant à la réponse précédente, sur Mac OS X, le "script" peut être utilisé comme ci-dessous ...
script -q /dev/null commands...
Mais, comme il peut changer le code retour de "\ n" en "\ r\n", j'avais besoin de courir comme ça.
script -q /dev/null commands... | Perl -pe 's/\r\n/\n/g'
S'il y a un tuyau entre ces commandes, vous devez vider stdout. par exemple:
script -q /dev/null commands... | Ruby -ne 'print "....\n";STDOUT.flush' | Perl -pe 's/\r\n/\n/g'
Trop nouveau pour commenter la réponse spécifique, mais je pensais faire un suivi sur la fonction faketty
publiée par ingomueller-net ci-dessus depuis qu'elle m'a récemment aidé.
J'ai trouvé que cela créait un fichier TypeScript
dont je ne voulais pas/dont j'ai besoin, j'ai donc ajouté/dev/null comme fichier cible du script:
function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }
J'essayais d'obtenir des couleurs lors de l'exécution de shellcheck <file> | less
, j'ai donc essayé les réponses ci-dessus, mais elles produisent cet effet bizarre où le texte est décalé horizontalement par rapport à l'endroit où il devrait être:
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.
(Pour ceux qui ne connaissent pas le shellcheck, la ligne avec l'avertissement est censée correspondre à l'endroit où se trouve le problème.)
Pour que les réponses ci-dessus fonctionnent avec shellcheck, j'ai essayé l'une des options des commentaires:
faketty() {
0</dev/null script -qfc "$(printf "%q " "$@")" /dev/null
}
Cela marche. J'ai également ajouté --return
et utilisé des options longues, pour rendre cette commande un peu moins impénétrable:
faketty() {
0</dev/null script --quiet --flush --return --command "$(printf "%q " "$@")" /dev/null
}
Fonctionne dans Bash et Zsh.
Il y a aussi un programme pty inclus dans l'exemple de code du livre "Programmation avancée dans l'environnement UNIX, deuxième édition"!
Voici comment compiler pty sur Mac OS X: