187 votes

Comment faire croire à une application que sa sortie d'écran est un terminal et non un tuyau ?

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 parce qu'elle détecte un pipe sur STDOUT, et je veux qu'elle pense qu'il s'agit d'un terminal interactif afin d'obtenir la même sortie lors de la redirection.

Je pensais que l'envelopper dans un expect script ou en utilisant un fichier proc_open() en PHP devrait le faire, mais ce n'est pas le cas.

Des idées ?

16voto

Jonas Berlin Points 719

Mise à jour de la réponse de @A-Ron à a) fonctionner à la fois sur Linux et MacOs b) propager le code d'état indirectement (puisque MacOs script ne le supporte pas)

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
}

Exemples :

$ 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

9voto

A-Ron Points 91

C'est trop récent pour commenter la réponse spécifique, mais j'ai pensé que je devais faire un suivi de la question suivante faketty fonction postée par ingomueller-net ci-dessus car elle m'a récemment aidé.

J'ai découvert que cela créait un typescript dont je n'avais pas besoin, j'ai donc ajouté /dev/null comme fichier cible script :

function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }

3voto

frank Points 1

Il y a aussi un programme pty inclus dans l'exemple de code du livre "Advanced Programming in the UNIX Environment, Second Edition" !

Voici comment compiler pty sur 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 *

3voto

Nick ODell Points 1705

J'essayais d'obtenir des couleurs quand on exécute shellcheck <file> | less sous Linux, 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 sont pas familiers avec shellcheck, la ligne avec l'avertissement est censée être alignée avec 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 proposées dans les commentaires :

faketty() {                       
    0</dev/null script -qfc "$(printf "%q " "$@")" /dev/null
}

Cela fonctionne. 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 en Bash et Zsh.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X