Capture stdout à une variable, mais toujours l'afficher dans la console
J'ai un script bash qui appelle plusieurs processus long. Je veux capturer la sortie de ces appels dans des variables pour le traitement de raisons. Cependant, parce que ce sont de longs processus en cours d'exécution, je voudrais la sortie de la rsync appels à afficher dans la console dans en temps réel et pas après le fait.
À cette fin, j'ai trouvé un moyen de le faire, mais il s'appuie sur la sortie du texte à /dev/stderr. J'ai l'impression que la sortie vers /dev/stderr n'est pas une bonne façon de faire les choses.
VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)
VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)
VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)
Dans l'exemple ci-dessus, je suis d'appel rsync un peu de temps et je veux voir les noms de fichiers comme ils sont traités, mais à la fin j'ai encore envie de la sortie dans une variable parce que je vais être l'analyser plus tard.
Est-il un "cleaner" pour cela?
Si cela fait une différence, j'utilise Ubuntu 12.04, bash 4.2.24.
Vous devez vous connecter pour publier un commentaire.
Double &1 dans votre shell (dans mon exemple à 5) et de l'utiliser &5 dans le shell interne est exécuté (de sorte que vous allez écrire sur la sortie standard (&1) de la mère shell):
Imprime aaa deux fois, parce que de l'écho dans le shell interne est exécuté, et le deuxième temps d'impression de la valeur de la variable.
Dans votre code:
exec 5>&-
alors?FF=$(echo aaa | tee /dev/tty)
? Source5
se réfère à/dev/fd/63
?tee: /dev/fd/63: No such file or directory
tee >(inner_cmd...)
, la coquille s'ouvre un tuyau à l'intérieur de la commande, tels que la conduite d'écrire du côté est également héritée par l'extérieur de la commande (eto), généralement sous le descripteur de 63. L'extérieur de commande n'a aucune idée de la coquille n'a rien de drôle, il devient un argument de nom de fichier/dev/fd/63
. en.wikipedia.org/wiki/Process_substitution Ne sais pas pourquoi vous avez eu cette erreur, mais il n'a aucun rapport avec commande intérieure de l'écriture de descripteur 5.Op De Cirkel, en réponse a la bonne idée. Il est possible de simplifier encore plus (évitant l'utilisation de
cat
):tee /dev/fd/1
, mais cela ne fonctionne pas parce que la sortie est toujours capturé par$()
. Donc, au cas où quelqu'un d'autre se pose la question de la même chose, c' est nécessaire d'utiliser un descripteur de fichier (5).exec
:{ FF=$(echo aaa|tee /dev/fd/5); } 5>&1
Les accolades permettent de redirection de se produire avant que le shell interne est exécuté commande est exécutée, alors que$FF
reste toujours dans le champ d'application du shell courant (qui ne fonctionne pas avec la normale crochets(
)
. De cette façon, il n'y a même pas besoin de fermer FD 5 par la suite, qui est un négligé d'hygiène habitude.Voici un exemple de capture à la fois
stderr
et la commande de code de sortie. C'est en s'appuyant sur la réponse de Russell Davis.Si le dossier
/taco/
existe, cela permettra de capturer son contenu. Si le dossier n'existe pas, il capture un message d'erreur et le code de sortie 2.Si vous omettez
2>&1
alors seulementstdout
va être capturée.Vous pouvez utiliser plus de trois descripteurs de fichiers. Essayer ici:
http://tldp.org/LDP/abs/html/io-redirection.html
"Ouvrir chaque fichier est assigné un descripteur de fichier. [2] Les descripteurs de fichier pour stdin, stdout, et stderr sont 0, 1 et 2, respectivement. Pour l'ouverture des fichiers supplémentaires, il reste des descripteurs de 3 à 9. Il est parfois utile d'utiliser une de ces descripteurs de fichiers pour stdin, stdout ou stderr, à titre temporaire, le lien dupliquer."
Le point est de savoir si cela vaut la peine de faire un script plus compliqué juste pour arriver à ce résultat. En fait c'est pas vraiment un problème, la façon dont vous le faites.
Si par "la console" vous voulez dire que votre ATS, essayez
C'est un peu douteux en pratique parce que les personnes qui essayer d'utiliser ce sont parfois surpris lors de la sortie de terres dans des endroits inattendus quand ils n'ont pas un ATS (cron d'emplois, etc.).
Alternative à l'utilisation de
/dev/tty
ou d'un autre descripteur de fichier, tel que suggéré par les autres réponses, vous pouvez aussi le retourner et il suffit d'utiliser un fichier temporaire. C'est sans doute plus facile à lire et plus portable dans certaines situations.