Skip to content

Comment débuffer la sortie passée d'une commande interactive dans un pipeline se terminant par `tee` ?

Après avoir cherché dans divers référentiels et sites Internet, nous avons finalement trouvé la réponse que nous partageons ici.

Solution :

Substitution de processus 1 vous permet de transformer un script typecript au fur et à mesure qu'il est écrit.

Vous pouvez utiliser script -q >(./dewtell >>outfile) brew args... au lieu de script -aq outfile brew args... pour écrire un journal avec les séquences d'échappement supprimées, où ./dewtell est la commande qui exécute le script qui les supprime. Sur d'autres systèmes que les versions relativement récentes de macOS ou FreeBSD, la commande sera légèrement différente, parce que différentes script supportent différentes options. Voir ci-dessous pour tous les détails.

L'histoire jusqu'ici (y compris les solutions alternatives)

Votre solution

Votre brew exécute de nombreux autres programmes générant des résultats en tant que sous-processus, tels que ./configure scripts et makeet vous avez constaté que le fait de faire passer brewvers tee avec brew args... 2>&1 | tee -a outfile fait que la sortie (d'au moins certains de ces sous-processus) est mise en mémoire tampon et n'apparaît pas sur votre terminal en temps réel.

Vous avez constaté que l'utilisation de script, en exécutant script -aq, a résolu ce problème en conservant la sortie standard un terminal.2, et que vous pouvez également passer -k si vous voulez que votre propre entrée soit enregistrée même dans les situations où elle n'est pas répercutée dans le terminal au fur et à mesure que vous la tapez.. Vous avez trouvé en outre que la version étendue de dewtell du script Perl de Gilles pour supprimer les séquences d'échappement des fichiers nettoie efficacement le typecript généré, le transformant en ce dont vous avez besoin.

La différence entre le script original de Gilles et la version étendue de dewtell est que, bien qu'ils suppriment tous deux les séquences d'échappement, y compris, mais sans s'y limiter, celles qui spécifient les changements de couleur, le script de dewtell supprime également les caractères de retour chariot ($'r'représentés par ^M dans vim et dans la sortie de cat -v) ainsi que les caractères de retour arrière ($'b'représenté par ^H dans vim et dans la sortie de cat -v) et les caractères, s'il y en a, qu'ils semblent avoir effacés.

Problèmes avec certaines implémentations de Perl

Vous avez signalé que le script nécessite un interpréteur Perl "relativement récent". Mais il ne fait pas appel à des fonctionnalités plus récentes avec... use ou semble autrement en dépendre, et un de mes amis qui exécute macOS 10.11.6 El Capitan a vérifié qu'il fonctionne avec le perl 5.8.12 fourni par le système, donc je ne sais pas pourquoi (ou si) vous aviez besoin d'un perl plus récent. J'attends la plupart des les gens peuvent juste utiliser le perl qu'ils ont.

Mais le script a échoué sur Mac OS X 10.4.11 Tiger (PPC) avec le système fourni par perl 5.8.6, qui croit à tort (au moins sur mon système) que m n'est pas dans la classe de caractères [@-~]même avec LC_COLLATE=C ou LC_ALL=C et même si le système fourni par grep, sed, pythonet ruby n'ont pas ce problème. Cela a provoqué des morceaux de séquences d'échappement spécifiant la couleur qui sont restés dans la sortie, car les séquences n'ont pas réussi à correspondre à... (?:e[|x9b) [ -?]* [@-~] et correspondaient à l'alternative ultérieure e. à la place. Avec perlbrew, j'ai installé perl 5.27.5, 5.8.9 et même 5.6.2 sur ce système ; aucun n'avait le problème.

Si l'on a besoin ou si l'on veut exécuter le script avec un interpréteur Perl installé ailleurs qu'en /usr/bin/perl./usr/bin/perl, alors on peut changer la ligne hashbang en haut de page pour le chemin correct ; ou on peut la changer en /usr/bin/env perl si l'on souhaite perl souhaité apparaît en premier dans le chemin, c'est-à-dire s'il s'exécuterait si on tapait perl et que l'on appuie sur Entrez; ou on peut invoquer l'interpréteur explicitement avec le nom de fichier du script comme premier argument, par ex, /usr/local/bin/perl dewtell au lieu de ./dewtell.

Méthodes pour conserver ou remplacer le script original

Certains utilisateurs qui doivent supprimer les séquences d'échappement d'un tapuscrit voudront également conserver l'ancien tapuscrit non traité. Si un tel utilisateur souhaite traiter un tapuscrit appelé dirty.log et écrire la sortie dans clean.logil doit exécuter ./dewtell dirty.log > clean.logen remplaçant si nécessaire ./dewtell par toute autre commande exécutant le script dewtell (ou un autre script qu'ils souhaitent utiliser).

Pour modifier le script type "en place" à la place, on peut passer la commande -i à perlen exécutant perl -i.orig dewtell typescripttypescript est le script généré par script, .orig est tout suffixe à utiliser pour le fichier de sauvegarde, et dewtell est le script Perl. Ou on peut plutôt exécuter perl -i dewtell typescriptqui élimine l'original car aucun suffixe de sauvegarde n'est fourni. Ces méthodes ne fonctionnent pas avec tous les scripts Perl mais elles fonctionnent avec celui-ci car il utilise <> pour lire l'entrée, et <> en Perl respecte -i.

Vous avez utilisé sponge pour réécrire les modifications dans le typecript original. Cette méthode est également bonne et fiable, bien qu'elle nécessite que moreutils soit installé.

Empêcher les séquences d'échappement d'être jamais enregistrées.

La question qui reste est de savoir comment écrire un journal dans lequel les séquences d'échappement sont supprimées en premier lieu. Comme vous le dites :

[T]l se peut en outre qu'il y ait un moyen de ficeler tout cela dans un seul pipeline, mais je n'ai pas été en mesure de le comprendre à ce jour ; des commentaires ou des réponses supplémentaires montrant comment....

Utiliser la substitution de processus au lieu d'un pipeline.

Le problème est le suivant . script sur la plupart (tous ?) des systèmes n'a pas d'option pour supporter ces transformations. Depuis script écrit dans un fichier dont vous spécifiez le nom ou dont le nom par défaut est typescript--pas dans la sortie standard--piping à partir de script n'affecterait pas ce qui est écrit dans le typecript.

Placer le script sur le côté droit de l'opérateur pipe (|) pour envoyer à ce n'est pas non plus une bonne idée. Dans votre cas, c'est spécifiquement parce que la sortie de brew ou de ses sous-processus était mise en mémoire tampon lorsque sa sortie standard était un tuyau, de sorte qu'elle n'apparaissait pas lorsque vous aviez besoin de la voir.

Même si ce problème était résolu, je ne connais pas de moyen raisonnable d'utiliser un fichier pipeline1 conjointement avec script pour accomplir cette tâche.

Mais cela peut être fait avec la substitution de processus.3 Dans la substitution de processus 1 (également expliquée ici), on écrit <(command...) ou >(command...). L'interpréteur de commandes crée un tuyau nommé et l'utilise comme sortie ou entrée standard, respectivement, pour une sous-exécution dans laquelle command... est exécuté. Le texte <(command...) ou >(command...) est remplacé par le nom de fichier du tuyau nommé - c'est le texte substitution--ainsi vous pouvez le passer comme argument à un programme ou l'utiliser comme cible d'une redirection.

  • Utilisez <(command...) pour exécuter command... comme sa sortie est le contenu d'un fichier que vous lire à partir de.4
  • Utiliser >(command...) pour exécuter command... comme son entrée est le contenu d'un fichier que vous écrire vers.4

Tous les systèmes ne supportent pas les named pipes, mais la plupart le font. Tous les interpréteurs de commandes ne prennent pas en charge la substitution de processus, mais Bash le fait, tant qu'il fonctionne sur un système capable de la prendre en charge, que votre compilation de Bash n'a pas omis de la prendre en charge et que le mode POSIX est désactivé dans l'interpréteur de commandes. Dans Bash, vous généralement avez accès à la substitution de processus, surtout si vous utilisez un système d'exploitation récent. Même sur mon système Mac OS X 10.4.11 Tiger (PPC) où "$BASH_VERSION" est 2.05b.0(1)-releasela substitution de processus fonctionne très bien.

Voici comment faire en utilisant script's syntaxe sur un système macOS récent.

Cela devrait fonctionner sur votre système macOS 10.11 El Capitan - et, d'après cette page de manuel, sur n'importe quel système macOS. au moins aussi ancien que macOS 10.9 Mavericks. et peut-être même avant :

script -q >(./dewtell >>clean.log) brew args...

Cela enregistre tout ce qui est écrit dans le terminal, y compris votre propre entrée... si elle vous est renvoyée en écho, c'est-à-dire si elle apparaît dans le terminal, ce qui est généralement le cas. Si vous voulez que votre propre entrée soit journalisée même si elle n'apparaît pas, en gardant à l'esprit que la situation dans laquelle cela se produit est souvent que vous entrez un mot de passe, alors, comme vous l'avez mentionné dans votre réponse, ajoutez la balise -k option :

script -kq >(./dewtell >>clean.log) brew args...

Dans les deux cas, remplacez ./dewtell par la commande qui exécute le script dewtell ou tout autre programme ou script que vous souhaitez utiliser pour filtrer la sortie, clean.log par le nom du fichier dans lequel vous voulez écrire le script de type avec les séquences d'échappement omises, et brew args...5 avec la commande que vous exécutez et ses arguments.

Écraser ou ajouter au journal

Si vous voulez écraser clean.log au lieu de l'annexer, alors utilisez >clean.log au lieu de >>clean.log. Le fichier réel est écrit par la commande qui est exécutée via la substitution de processus, donc la commande > ou >> apparaît dans l'opérateur de redirection >().

Ne tentez pas d'utiliser >>( à la place de >(ce qui est une erreur de syntaxe et n'a pas de sens, car l'option > dans >( pour la substitution de processus ne signifie pas la redirection.

Ne pas passer -a à script dans l'intention que cela empêche votre fichier journal d'être écrasé dans cette situation, car cela ouvrirait simplement le tuyau nommé en mode append - ce qui a le même effet que de l'ouvrir pour une écriture normale - et ensuite, soit écraser, soit annexer clean.log toujours en fonction du fait que >clean.log ou >>clean.log est utilisé dans la sous-coquille.

De même, n'utilisez pas >& ou &> ou ajoutez 2>&1 à l'intérieur de >() (ou n'importe où), car si ./dewtell génère des erreurs ou des avertissements, vous voudriez les voir plutôt que de les voir écrits dans le fichier clean.log. Le site script inclut automatiquement le texte de l'erreur standard dans son typecript ; vous n'avez pas besoin de faire quoi que ce soit de spécial pour y parvenir.

Sur d'autres systèmes d'exploitation

Comme le dit votre réponse :

[S]ertaines versions de la script ont une syntaxe différente ; celle qui est donnée est pour OS X/macOS, donc à ajuster si nécessaire.

GNU/Linux

La plupart des systèmes GNU/Linux utilisent la commande script fournie par util-linux. Si vous souhaitez qu'elle exécute une commande spécifique plutôt que de lancer un shell, vous devez utiliser l'implémentation -c et passer la commande entière en tant que un seul argument de ligne de commande à scriptce que vous pouvez obtenir en le mettant entre guillemets. Ceci est différent de la version de script sur les systèmes macOS récents comme le vôtre, qui vous permet de passer la commande naturellement comme plusieurs arguments placés après le nom du fichier de sortie (sans option comme -c).

Donc sur Debian, Ubuntu, Fedora, CentOS, et la plupart des autres systèmes GNU/Linux, vous pourriez utiliser cette commande (s'il y avait un brew commande 6, ou en la remplaçant par n'importe quelle commande que vous voulez exécuter et enregistrer la sortie transformée) :

script >(./dewtell >>clean.log) -qc 'brew args...'

Comme avec script sur votre système, sur GNU/Linux supprimez -q si vous voulez script pour inclure plus de messages sur la façon dont la journalisation a commencé et s'est terminée. Même avec l'option -q cette version de script inclut toujours une ligne en haut indiquant quand elle a commencé à fonctionner, bien qu'elle ne montre pas vous cette ligne et il n'écrit ni ne montre rien sur la date à laquelle il a arrêté de fonctionner.

Il n'y a pas de -k option. Seul le texte qui apparaît dans le terminal est enregistré.7

FreeBSD

Le site script dans macOS provient de FreeBSD. Toutes les versions supportent -a pour ajouter au lieu d'écraser (bien que, comme indiqué ci-dessus, cela ne vous aide pas à ajouter lorsque vous écrivez via un tuyau nommé en utilisant la substitution de processus). -a était la seule option jusqu'à et y compris FreeBSD 2.2.5. L'adresse -q a été ajoutée dans FreeBSD 2.2.6. L'adresse -k a été ajoutée dans FreeBSD 2.2.7.

Jusqu'à FreeBSD 2.2.5, l'option script ne permettait pas de donner une commande spécifique, mais à la place exécutait toujours le shell de l'utilisateur, donné par l'option SHELL la variable d'environnement, avec /bin/sh comme solution de repli si la variable n'est pas définie. A partir de FreeBSD 2.2.6, une commande spécifique pouvait être donnée sur la ligne de commande à script qui l'exécuterait à la place d'un shell.

Ainsi, les versions ultérieures de FreeBSD, y compris celles que l'on rencontre couramment aujourd'hui, sont similaires aux systèmes macOS plus récents comme le vôtre dans la manière dont la commande script peut être invoquée. De même, les anciennes versions de FreeBSD sont similaires aux anciennes versions de macOS (voir ci-dessous).

Notez que perl ne fait pas partie du système de base de FreeBSD dans aucune version récente, et que bash ne l'a jamais été. Les deux peuvent être facilement installés en utilisant des paquetages (comme avec pkg install perl5 bash bash-completion) ou des ports. Le système fourni par /bin/sh sous FreeBSD ne supporte pas la substitution de processus.

Les anciennes versions de macOS, et tout autre système avec un système moins polyvalent. script

J'ai fait des tests sur Mac OS X 10.4 Tiger où script accepte seulement le -a option. Il n'accepte pas -q ou -k. Il n'inclut dans son script que les frappes de touches affichées dans le terminal.7, comme avec la version util-linux sur les systèmes GNU/Linux.

Au moins jusqu'à ce que je puisse trouver une source fiable de documentation pour la version de script dans chaque version de macOS (à ma connaissance, seules les manpages de 10.9 Mavericks sont facilement accessibles en ligne), Je recommande aux utilisateurs de macOS d'exécuter man script pour vérifier quelle syntaxe leur script accepte, comment elle se comporte par défaut, et quelles options elle prend en charge. Vous voudriez utiliser ces commandes sur une ancienne version de macOS comme la mienne :

script >(./dewtell >>clean.log)
brew args...
exit

Ceci s'applique également à scriptsur tout autre OS où il ne prend pas en charge de nombreuses options. ou sur les systèmes d'exploitation où d'autres options sont prises en charge mais où vous préférez ne pas les utiliser. Cette méthode d'utilisation de script pour démarrer un shell, exécuter la ou les commandes du shell dont vous avez besoin d'être enregistré, puis quitter le shell, est la méthode traditionnelle.

Le vilain hack consistant à prétendre que votre commande est votre shell.

Si vous devez vraiment utiliser script pour exécuter une seule commande plutôt qu'une nouvelle instance de votre shell, il y a un hack laid que vous pouvez parfois utiliser : vous pouvez le tromper en lui faisant croire que la commande que vous voulez exécuter est en fait votre shell avec SHELL=your-command script outfile. Vous devriez cependant réfléchir à deux fois avant de faire cela, car si your-command lui-même consulte effectivement la commande SHELL variable d'environnement pour vérifier quel shell réel vous utilisez, hilarité un comportement malheureux s'ensuivrait.

En outre, cela ne fonctionnera pas facilement pour une commande composée de plusieurs mots - c'est-à-dire une commande à laquelle vous passez un ou plusieurs arguments. Si vous avez écrit SHELL='brew args...' avant script sur la même ligne, cela réussirait à faire passer brew args... dans scripten tant que valeur de SHELL, mais cette chaîne entière serait utilisée comme nom de la commande, plutôt que juste le premier mot, et aucun argument ne serait passé à la commande, plutôt que tous les autres mots soient passés.

Vous pourriez contourner ce problème en écrivant un script shell, appelé . run-brew ou quel que soit le nom que vous voulez lui donner, qui exécute brew avec args... et passe ensuite cela comme valeur de la fonction SHELL comme valeur de la variable d'environnement SHELL. Après avoir fait le run-brew vous pouvez l'exécuter via la commande script pourrait ressembler à ceci :

SHELL=run-brew script >(./dewtell >>clean.log)

Pour les raisons évoquées ci-dessus, je déconseille d'utiliser la méthode consistant à attribuer votre nom de commande à la commande SHELL, sauf si l'action que vous effectuez est sans importance ou si vous êtes sûr qu'elle n'impliquera pas l'utilisation de la commande SHELL. Comme Homebrew effectue de nombreuses actions assez compliquées, je vous déconseille d'exécuter réellement une commande de type run-brew comme celui-ci. (Il n'y a rien de mal à mettre votre long, compliqué brew dans un script run-brew mais seulement d'utiliser SHELL=run-brew pour faire script l'exécuter).

J'ai trouvé cette méthode un peu utile en testant les techniques présentées ci-dessus avec un programme simple à la place de... brew args..., cependant.

Test et démonstration de la technique

Vous pouvez trouver utile d'essayer certaines de ces méthodes sur une commande moins compliquée que votre longue... brew commande. Je sais que je l'ai fait.

Le programme de démonstration / générateur d'entrées de test, et la méthode de test utilisée.

J'ai fait ce script Perl interactif simple qui écrit sur l'erreur standard, demande à l'utilisateur sur la sortie standard son nom, le lit sur l'entrée standard, puis écrit une salutation sur la sortie standard avec le nom de l'utilisateur en couleur :

#!/usr/bin/perl

use strict;
use warnings;
use Term::ANSIColor;

print STDERR $0, ": warning: this program is boringn";
print "What's your name?  ";
chomp(my $name = );
printf "Hello, %s!n", colored($name, 'cyan');

Je l'ai appelé colorhi et je l'ai mis dans le même répertoire que le script dewtell, que j'ai appelé dewtell.

Dans mes propres tests, j'ai remplacé #!/usr/bin/perl par #!/usr/bin/env perl dans les deux scripts.8 J'ai testé dans Ubuntu 16.04 LTS avec le perl 5.22.1 fourni par le système et les versions 5.6.2 et 5.8.9 fournies par... perlbrew; FreeBSD 11.1-RELEASE-p3 avec la version de pkg-perl 5.24.3 et les versions 5.6.2, 5.8.9 et 5.27.5 fournies par le système. perlbrew; et Mac OS X 10.4.11 Tiger avec le système fourni perl 5.8.6 et les versions 5.6.2, 5.8.9, et 5.27.5 fournies par perlbrew.

J'ai répété les tests décrits ci-dessous avec chacune de ces versions de perl, en testant d'abord la version fournie par le système.9 fournie par le système, puis en utilisant la version perlbrew use pour provoquer temporairement chaque perlbrew-fourni perl apparaisse en premier dans $PATH (par exemple, pour tester perl 5.6.2, j'ai exécuté perlbrew use 5.6.2, puis les commandes présentées ci-dessous pour le système sur lequel je testais).

Un ami l'a testé dans macOS 10.11.6 El Capitan, avec les lignes de hashbang originales, provoquant l'utilisation de perl 5.18.2 fourni par le système, et ne testant aucun autre interprète. Ce test a employé les mêmes commandes que j'ai exécutées lors des tests sur FreeBSD.

Tous ces tests ont réussi sauf avec le perl fourni par le système dans Mac OS X 10.4.11 Tiger., qui a échoué en raison de ce qui semble être un bogue étrange impliquant les classes de caractères dans les expressions régulières, comme je l'ai décrit précédemment en détail, et comme indiqué ci-dessous dans un exemple.

Sur Ubuntu

Alors que je me trouvais dans le répertoire qui contenait les scripts, j'ai exécuté ces commandes sur le système Ubuntu pour produire un typecript avec des séquences d'échappement et tous les caractères de retour arrière que je pourrais taper :

printf 'Whatever header you want...nn' >dirty.log
script dirty.log -aqc ./colorhi

J'ai tapé Eliahpuis j'ai agi comme si j'avais mieux réfléchi, en l'effaçant avec des espaces arrière et en tapant Bob from accounting à la place. Puis j'ai tapé Entrez et j'ai été accueilli en couleur. Puis j'ai exécuté ces commandes pour séparément produire un typecript sans séquences d'échappement et sans aucun signe de mon vrai nom, en interagissant avec lui exactement de la même manière (y compris en tapant et en effaçant. Eliah):

printf 'Whatever header you want...nn' >clean.log
script >(./dewtell >>clean.log) -qc ./colorhi

vim affiche les caractères de contrôle symboliquement comme cat -v et offre l'avantage d'un texte éclairci ou coloré. C'est ce que fait le tampon affiché par view dirty.log ressemblait, mais avec les représentations des caractères de contrôle en italique pour qu'ils ressortent ici :

Whatever header you want...

Script started on Thu 09 Nov 2017 07:17:19 AM EST
./colorhi: warning: this program is boring^M
What's your name?  Eliah^H ^H^H ^H^H ^H^H ^H^H ^HBob from accounting^M
Hello, ^[[36mBob from accounting^[[0m!^M

Et voici à quoi ressemblait le tampon pour view clean.log:

Whatever header you want...

Script started on Thu 09 Nov 2017 07:18:31 AM EST
./colorhi: warning: this program is boring
What's your name?  Bob from accounting
Hello, Bob from accounting!

Les résultats étaient les mêmes avec chaque interprète testé, sauf bien sûr pour l'horodatage.

Sur FreeBSD (et macOS 10.11.6 El Capitan)

J'ai effectué le test de la même manière sur FreeBSD que sur Ubuntu, sauf que j'ai utilisé ces commandes pour produire... dirty.log:

printf 'Whatever header you want...nn' >dirty.log
script -aq dirty.log ./colorhi

Et j'ai utilisé ces commandes pour produire clean.log:

printf 'Whatever header you want...nn' >clean.log
script -q >(./dewtell >>clean.log) ./colorhi

Ce sont les mêmes commandes que mon ami a utilisé pour tester ceci sur macOS 10.11. et bien que l'entrée émise ait été légèrement différente de mon Eliah/Bob from accounting entrée, un nom était toujours tapé, effacé avec des espaces arrière, et remplacé par un autre nom. La sortie était donc similaire, sauf pour les noms et le nombre de backspaces.

Avec les quatre implémentations de Perl testées sur FreeBSD et l'unique implémentation (fournie par le système) sur macOS 10.11, les deux implémentations dirty.log et clean.log a montré le résultat attendu. En comparant les résultats de FreeBSD avec ceux d'Ubuntu, la différence était l'absence d'horodatage, en raison des éléments suivants -q. Toutes les séquences d'échappement et les retours de chariot ont été supprimés avec succès dans clean.log. clean.log, ainsi que tous les backspaces et les caractères dont l'effacement était indiqué par les backspaces.

Sur Mac OS X 10.4.11 Tiger

J'ai effectué le test de la même manière sur mon vieux système Tiger que sur Ubuntu et FreeBSD, sauf que j'ai utilisé ces commandes pour produire... dirty.log:

printf 'Whatever header you want...nn' >dirty.log
SHELL=colorhi script -a dirty.log

Et j'ai utilisé ces commandes pour produire clean.log:

printf 'Whatever header you want...nn' >clean.log
SHELL=colorhi script >(./dewtell >>clean.log)

Puisque le système script ne supporte pas la commande -qles résultats comprennent à la fois (a) a Script started ajoutée après l'en-tête et (b) un saut de ligne suivi d'une Script done ligne ajoutée à la toute fin de chaque tapuscrit. Ces deux lignes contenaient des horodatages. En dehors de cela, les résultats étaient les mêmes que sur Ubuntu et FreeBSD, sauf que les séquences d'échappement pour passer du texte cyan au texte cyan et vice-versa n'ont pas été entièrement supprimées par le système. perl. La ligne pertinente de dirty.log apparaît toujours de cette façon dans vim, comme prévu :

Hello, ^[[36mBob from accounting^[[0m!^M

Avec le perl 5.8.6 fourni par le système, c'était la ligne correspondante dans clean.log , montrant 6m et 0mqui auraient dû être enlevés et laissés de côté :

Hello, 6mBob from accounting0m!

Avec chacun des perlbrew-installée, toutes les séquences d'échappement ont été entièrement et correctement supprimées, et cette ligne dans le fichier clean.logressemblait à ceci, tout comme avec tous les interpréteurs Perl que j'ai exécutés sur Ubuntu et FreeBSD :

Hello, Bob from accounting!

Notes

1 Ce manuel est pour Bash 2. De nombreux utilisateurs de Bash sont sur la version majeure 4 et préféreront lire sur la substitution de processus, les pipelines et d'autres sujets dans le manuel actuel de Bash. Les versions actuelles de macOS sont livrées avec Bash 3.

2 L'erreur standard est presque toujours non tamponnée, quel que soit le type de fichier ou de périphérique. Il n'y a pas de règle selon laquelle les programmes ne peuvent pas mettre en mémoire tampon les écritures sur le descripteur de fichier 2, mais il y a une forte tradition de ne pas le faire, basée sur le besoin de voir réellement les messages d'erreur et d'avertissement lorsqu'ils se produisent - et aussi le besoin de les voir... du tout même si le programme se termine anormalement sans jamais fermer correctement ou vider ses descripteurs de fichiers ouverts. Ce serait généralement un bug pour un programme de mettre en mémoire tampon les écritures sur l'erreur standard par défaut.

3 La substitution de processus utilise un tuyau nommé également appelé un FIFO, qui atteint le même objectif général que l'opérateur pipe | dans les shells, mais est plus polyvalent. Cependant, même si cet opérateur est un pipe, je considère qu'il n'est pas une canalisation, que je considère comme désignant la construction syntaxique spécifique et le comportement correspondant d'un shell.

4 Si vous considérez un pipe nommé comme un fichier, ce que vous devriez faire, alors c'est littéralement ce qui se passe.

5 Bien que "$COMMAND" apparaisse dans votre réponse et transmette une commande entière comme un seul argument à script (parce que les guillemets doubles suppriment le découpage des mots), vous avez pu transmettre la commande à script en tant qu'arguments multiples.

6 Comme avec Linuxbrew, que je dois reconnaître que vous m'avez fait découvrir.

7 Cependant, je recommande à toute personne qui compte sur ce comportement pour garder secrètes des données sensibles de tester le comportement de ses script et peut-être même d'inspecter les typescripts générés pour s'assurer qu'aucune donnée qui doit être protégée n'est présente. Pour être encore plus sûr, utilisez un éditeur qui affiche les caractères qui seraient ordinairement cachés à l'écran, ou utilisez la commande cat -v.

8 Les versions avec #!/usr/bin/perly compris la version colorhi présentée, devraient fonctionner et faire la bonne chose sur la plupart des systèmes. J'ai utilisé #!/usr/bin/env perl dans mes propres tests. Mais mon ami qui a le même système d'exploitation que vous (l'affiche originale) a utilisé #!/usr/bin/perl. Cela a atteint l'objectif de vérifier, avec un minimum de complication ou de potentiel de doute, que le perl fourni par le système fonctionnerait.

9 Sous FreeBSD il n'y a pas de perl fourni par le système au sens strict. J'ai testé la version installée via pkg premièrement.

Pensez à diffuser cet article si cela en valait la peine.



Utilisez notre moteur de recherche

Ricerca
Generic filters

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.