Unix: utilisation confuse de la commande Tee

Manual indique que le tee est un “raccord de tuyau”. Les cas [1] me confondent:

1. cas

echo "foo bar" | sudo tee -a /path/to/some/file 

2. cas

 :w !sudo tee % 

Il est difficile de comprendre la logique de départ des cas. Comment fonctionne le tee?

tee est normalement utilisé pour diviser la sortie d’un programme afin qu’il puisse être affiché et enregistré dans un fichier. La commande peut être utilisée pour capturer une sortie intermédiaire avant que les données ne soient modifiées par une autre commande ou un autre programme. La commande tee lit l’entrée standard, puis écrit son contenu sur la sortie standard. Il copie simultanément le résultat dans le ou les fichiers ou variables spécifiés

 tee [OPTION]... [FILE]... 

Par exemple

 tee [ -a ] [ -i ]... [ File ]... 
  • -a Ajoute la sortie à la fin du fichier au lieu de l’écrire.

  • -i Ignore les interruptions.

entrer la description de l'image ici

Avec sudo et ajout au fichier avec votre exemple dans la question

 ls -l | sudo tee -a file.txt 

tee est utilisé pour séparer un pipeline de commandes, ce qui vous permet d’enregistrer la sortie d’une commande dans un fichier et de l’ envoyer le long du pipeline. Dans le premier exemple que vous avez donné ::

 echo "foo bar" | sudo tee -a /path/to/some/file 

“foo bar” sera renvoyé à la sortie standard et ajouté à /path/to/some/file . Pensez à té comme un joint “T” dans un tuyau, divisant la sortie en deux autres tuyaux.

tee copie stdin sur stdout (comme cat ) et écrit tout dans le fichier nommé. En l’utilisant de cette façon avec sudo possible de pousser les informations dans un mode privilégié et, en même temps, de contrôler si les choses sont bien passées.

Notez également que, du fait de la manière dont la redirection est gérée dans le shell, son équivalent presque

 sudo echo "foo bar" > /path/to/some/file 

ne fonctionnera pas, car la redirection serait effectuée par l’utilisateur appelant et non par l’utilisateur cible sudo .

Explications pour les cas

1. l’escalade des permissions avec les commandes sudo- et -tee

L’exemple ne concerne pas uniquement la logique, mais plutôt la convention. Il montre la convention pour augmenter les permissions:

 echo "Body of file..." | sudo tee root_owned_file > /dev/null 

Cet exemple montre que tee est utilisé pour contourner une limitation inhérente à la commande sudo. sudo ne peut pas diriger la sortie standard vers un fichier. En vidant son stream stdout dans / dev / null, nous supprimons également la sortie en miroir de la console.

2. exécuter sudo-commands avec Vim

Comme vous pouvez utiliser les commandes Sudo avec Vim, vous pouvez utiliser la commande si vous avez oublié de l’exécuter en tant que sudo. Il est utile dans des endroits tels que /etc/init.d/, où vous trouverez des fichiers en lecture seule.

Logique avec la commande de départ

C’est comme une twig dans Git, ou mieux, s’il vous plaît, voir l’analogie de T par Rick Copeland . Espérons que l’exemple modifié (original) aide à comprendre son utilisation:

 curl "http://en.wikipedia.org/wiki/Pipeline_(Unix)" | tee original_site | sed 's/[^a-zA-Z ]/ /g' | tr 'AZ ' 'az\n' | grep '[az]' | sort -u | comm -23 - /usr/share/dict/words 

Rappelez-vous que la cible de tee n’est pas limitée aux fichiers normaux, mais peut être destinée à des périphériques, à des FIFO, etc. Vous pouvez également accéder à une autre invocation de tee , etc. 🙂

Je trouve que la commande tee est très utile pour déboguer les scripts shell contenant des pipelines longs. Il s’agit de la fin d’un sinistre script shell qui est en retard d’une décennie pour une réécriture en Perl, mais cela fonctionne toujours. (Il a été modifié pour la dernière fois en 1998, comme cela arrive.)

 # If $DEBUG is yes, record the intermediate results. if [ "$DEBUG" = yes ] then cp $tmp.1 tmp.1 cp $tmp.2 tmp.2 cp $tmp.3 tmp.3 tee4="| tee tmp.4" tee5="| tee tmp.5" tee6="| tee tmp.6" tee7="| tee tmp.7" fi # The evals are there in case $DEBUG was yes. # The hieroglyphs on the shell line pass on any control arguments # (like -x) to the sub-shell if they are set for the parent shell. for file in $* do eval sed -f $tmp.1 $file $tee4 | eval sed -f $tmp.3 $tee5 | eval sh ${-+"-$-"} $tee6 | eval sed -f $tmp.2 $tee7 | sed -e '1s/^[ ]*$/--@/' -e '/^--@/d' done 

Les trois scripts sed qui sont exécutés sont horribles – je ne prévois pas de les montrer. C’est aussi une utilisation semi-décente d’ eval . Les noms de fichiers temporaires normaux ($ tmp.1, etc.) sont conservés sous un nom fixe (tmp.1, etc.) et les résultats intermédiaires sont conservés dans tmp.4 .. tmp.7. Si je mettais à jour la commande, elle utiliserait "$@#" au lieu de ” $* ” comme indiqué. Et, quand je le débogue, il n’y a qu’un seul fichier dans la liste des arguments, donc le piétinement des fichiers de débogage n’est pas un problème pour moi.

Notez que si vous devez le faire, vous pouvez créer plusieurs copies de l’entrée à la fois. il n’est pas nécessaire d’alimenter une commande de tee dans un autre.

Si quelqu’un en a besoin, j’ai une variante de tee appelée tpipe qui envoie des copies de la sortie à plusieurs pipelines au lieu de plusieurs fichiers. Il continue même si l’un des pipelines (ou sortie standard) se termine tôt. (Voir mon profil pour les informations de contact.)

Le tee reflète simplement la sortie dans un fichier qui peut être spécifié comme argument de tee.

Dans le cas où vous montrez que tee est appelé en tant que super utilisateur (via sudo), son seul but est d’écrire un fichier en tant que super utilisateur à la place si l’utilisateur qui fait l’écho.

La commande tee crée simplement N + 1 no de fichiers, 1 copie transmise à stdout et d’autres aux arguments fournis à tee (c.-à-d. fichiers) où N: nombre d’agrégats transmis à tee