Disons que je redirige le STDOUT
, STDERR
d'un programme vers des files.
./script.sh 1> output.log 2> error.log
Est-ce que le programme courant peut le find, c'est-à-dire connaître les paths d'access à ces files?
Vous pouvez appeler lsof
pour listr les files ouverts du process shell. Utilisez -a -p $$
pour limiter la sortie au process shell ( $$
), -d 1
pour limiter la sortie au descripteur de file 1 (par exemple), et -F n
pour imprimer la sortie sous forme analysable. Voici un extrait de shell qui gère les caractères arbitraires dans les noms de file:
output_file=$(lsof -a -p $$ -d 1 -F pn; echo .) output_file=${output_file%.} output_file=${output_file#n}
Si le nom du file ne contient pas de nouvelle ligne, vous pourrez vous en sortir avec output_file=$(lsof -a -p $$ -d 1 -F pn | sed -n '2s/.//p')
.
Notez que le nom du file peut ne pas toujours exister, en particulier si le file a été supprimé.
Sous Linux, une autre façon d'accéder aux noms de files est de passer par /proc/$$/fd
: /proc/$$/fd/1
est un lien symbolique légèrement magique vers le file ouvert par le shell sur le descripteur de file 1 même si le nom de file returnné par readlink
n'existe pas, par exemple dans le cas d'un file supprimé).
C'est généralement une très mauvaise idée de faire un usage de l'information obtenue de cette façon. Si quelqu'un appelle votre script avec la sortie redirigée vers un file, il ne l'appréciera pas si vous vous comportez différemment en raison de l'location du file ou si vous n'affectez pas le file. Il y a une exception: vous pouvez réagir différemment selon que vous écrivez sur un terminal ou quelque chose d'autre (pipe, socket, file), par exemple pour afficher des colors ou des indicateurs de progression sur un terminal. Il existe un test spécifique pour déterminer si un descripteur de file est connecté à un terminal:
if [ -t 2 ]; then # stderr is a terminal printf 1>&2 '\e[31mError: widget not found\e[0m' else # stderr is not a terminal echo 1>&2 'Error: widget not found' fi
{ readlink /dev/fd/[1,2] ; echo "out" ; } >./file 2>./error { readlink /dev/fd/0 ; cat ; } <./file
SORTIE:
/home/mikeserv/file /home/mikeserv/file /home/mikeserv/error out { readlink /proc/$$/fd/[1,2] ; echo out ; } >./file 2>./error { readlink /proc/$$/fd/0 ; cat ; } <./file
SORTIE:
/home/mikeserv/file /home/mikeserv/file /home/mikeserv/error out
Dans votre cas, STDOUT
sera enregistré dans le file output.log
et STDERR
sera enregistré dans le file error.log
. Les deux files sont enregistrés dans le même directory avec script.sh
.
Si vous voulez que votre programme "connaisse le path vers ces files", vous devez utiliser le path absolu:
./script.sh > /path/to/output.log 2> /path/to/error.log
Les files output.log
et error.log
sont créés dans le directory courant, c'est-à-dire la valeur de la variable $PWD
. Si vous souhaitez que votre programme utilise ces files plus tard, sauvegardez leur directory dans une variable avant d'exécuter votre script. Voici un exemple :
OUTDIR=$PWD ./script.sh 1> output.log 2> error.log # Whatever you want to do else ... echo The output file : ======= cat $OUTDIR/output.log echo ========================= echo echo The errors file : ======= cat $OUTDIR/error.log echo =========================