Un script en cours d'exécution peut-il identifier le context de journalisation?

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 =========================