2016-02-14 1 views
1

J'utilise >(...) pour modifier ma sortie. Cela fonctionne mais l'ordre de sortie est en train de se foirer et je ne sais pas pourquoi.exec redirige vers le haut l'ordre de sortie dans bash

Dans le code ci-dessous I:

  1. sortie des lignes à la STDOUT normale
  2. sauver la STDOUT et STDERR
  3. modifier la sortie de STDOUT et STDERR en utilisant exec et >(..)
  4. envoyer la sortie au nouveau STDOUT et STDERR
  5. revenir à la sortie STDOUT et STDERR
  6. original Envoyer à STDOUT et STDERR

original, je me attends à la sortie pour ressembler # 1, # 4, # 6, mais ce que je reçois est classé n ° 1, # 6, # 4.

#!/bin/bash 

# output text to normal STDOUT 
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">' 
echo '<html>' 
echo " <head><title>daily backup script: ${now}</title></head>" 
echo ' <body style="font-family:monospace; font-size: 10px">' 
echo '  <table border="1">' 

# save STDOUT and STDERR 
exec 6>&1 
exec 7>&2 

# modify STDOUT 
exec 1> >(
    while read line 
    do 
     echo "   <tr><td>$(date +%Y-%m-%d)</td><td>$(date +%H:%M:%S)</td><td colSPan='5'>${line}</td></tr>" >&6 
    done 
) 

# modify STDERR 
exec 2> >(
    while read line 
    do 
     echo "   <tr style='color: red'><td>$(date +%Y-%m-%d)</td><td>$(date +%H:%M:%S)</td><td colSPan='5'>${line}</td></tr>" >&6 
    done 
) 

# output to new modified STDOUT and STDERR 
echo "test" 
echo "test again" >&2 
date 

# revert to original STDOUT and STDERR 
exec 1>&6 6>&- 
exec 2>&7 7>&- 

# output text to normal STDOUT 
echo '  </table>' 
echo ' </body>' 
echo '</html>' 

Je attends la sortie à ressembler à ceci:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
    <head><title>daily backup script: </title></head> 
    <body style="font-family:monospace; font-size: 10px"> 
     <table border="1"> 
      <tr><td>2016-02-13</td><td>20:08:01</td><td colSPan='5'>test</td></tr> 
      <tr style='color: red'><td>2016-02-13</td><td>20:08:01</td><td colSPan='5'>test again</td></tr> 
      <tr><td>2016-02-13</td><td>20:08:01</td><td colSPan='5'>Sat Feb 13 20:08:01 EST 2016</td></tr> 
     </table> 
    </body> 
</html> 

Mais c'est la production réelle:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
    <head><title>daily backup script: </title></head> 
    <body style="font-family:monospace; font-size: 10px"> 
     <table border="1"> 
     </table> 
    </body> 
</html> 
[email protected]:/path/to/script$    <tr style='color: red'><td>2016-02-13</td><td>20:11:29</td><td colSPan='5'>test again</td></tr> 
      <tr><td>2016-02-13</td><td>20:11:29</td><td colSPan='5'>test</td></tr> 
      <tr><td>2016-02-13</td><td>20:11:29</td><td colSPan='5'>Sat Feb 13 20:11:29 EST 2016</td></tr> 

Répondre

0

La première chose que je faisais était de créer une version simplifiée de votre cas de test avec juste quelques lignes de code. Il redirect juste stdout:

#!/bin/bash 
echo 1.message 
exec 6>&1 
exec 1> >(while read line ; do echo ${line} >&6 ; done) 
echo 2.message 
exec 1>&6 6>&- 
echo 3.message 

Je suppose que vous vous attendez à voir les messages de sortie dans cet ordre:

1.message 
2.message 
3.message 

mais ... non! J'ai été capable de reproduire votre problème. Si vous exécutez les quelques lignes de code ci-dessus, vous obtenez:

1.message 
3.message 
2.message 

Le problème d'un écho canalisé vers une boucle lecture en cours d'exécution dans un sous-shell est décrit here où ils disent:

. ..la lu agit comme si elle était en cours d'exécution dans un sous-shell ...

pour travailler autour de ce problème - et produire des messages dans l'ordre, je suppose que vous attendez, j'ai créé un nom pipe, re diriger stdout vers ce tube nommé. Ensuite, je ne FOURCHE un « vrai » et attendre sous-shell son achèvement ainsi:

#!/bin/bash 
mypipe=/tmp/$$.tmp 
trap "rm -f ${mypipe}" EXIT 
mknod ${mypipe} p 
echo 1.message 
exec 6>&1 
cat < ${mypipe} & 
exec 1>${mypipe} 
echo 2.message 
exec 1>&6 6>&- 
wait 
echo 3.message 

qui produisent:

1.message 
2.message 
3.message 
+0

J'ai essayé de comprendre comment intégrer dans ce que je suis en train de mais ne pas avoir beaucoup de chance.Fondamentalement, j'exécute une commande qui se répercutera sur les flux 'stdout' et' stderr'. Je veux modifier la sortie différemment en fonction du flux auquel la sortie est destinée. – IMTheNachoMan