Qual é o propósito de 'tee'?

86

Todos os usos de tee que eu já vi foram:

 do_something | tee -a logfile

Ou:

do_something_else | tee logfile

tee é inventado para aqueles que não sabem que você pode fazer o mesmo com os redirecionamentos de shell pipe? Tais como:

do_something >> logfile

Ou:

do_something_else > logfile

É praticamente o mesmo e são necessários menos acessos ao teclado para digitar. Quais recursos ocultos não estou vendo em tee ?

    
por R Moog 10.09.2018 / 13:14

10 respostas

240

O que você não vê é que do_something | tee -a logfile coloca a saída em logfile e em stdout, enquanto do_something >> logfile coloca somente no arquivo de log.

O propósito de tee é produzir um cenário de uma entrada e saída múltipla - assim como em um cruzamento 'T'.

EDITAR

Houve comentários sobre como tee permite um uso mais simples de sudo . Isso não vem ao caso: cat , dd ou talvez melhor buffer oferecem essa possibilidade com melhor desempenho, se você não precisar das várias saídas. Use tee para o que foi projetado, não para o que "também pode fazer"

    
por 10.09.2018 / 13:22
118

Tee não é inútil

Talvez você soubesse disso mesmo assim? Se não, continue lendo! Ou se você sabe como funciona, mas não tem certeza de porque existe, pule para o final e veja como ele se encaixa na filosofia Unix.

Qual é a finalidade de tee ?

Na sua forma mais simples, ele pega dados na entrada padrão e grava isso na saída padrão e em um (ou mais) arquivos. Ele foi comparado a uma peça do encanamento na maneira como divide uma entrada em duas saídas (e duas direções) .

Exemplos

Vamos dar o seu primeiro exemplo:

do_something | tee -a logfile

Isso pega a saída de do_something e a anexa ao arquivo de log, enquanto também o exibe para o usuário. Na verdade, a página da Wikipedia sobre tee tem isso como o segundo exemplo:

To view and append the output from a command to an existing file:

  lint program.c | tee -a program.lint

This displays the standard output of the lint program.c command at the computer and at the same time appends a copy of it to the end of the program.lint file. If the program.lint file does not exist, it is created.

O próximo exemplo tem outro uso: escalação de permissões :

To allow escalation of permissions:

cat ~/.ssh/id_rsa.pub | ssh admin@server "sudo tee -a /root/.ssh/authorized_keys2 > /dev/null"

This example shows tee being used to bypass an inherent limitation in the sudo command. sudo is unable to pipe the standard output to a file. By dumping its standard out stream into /dev/null, we also suppress the mirrored output in the console. The command above gives the current user root access to a server over ssh, by installing the user's public key to the server's key authorization list.

Ou talvez você queira pegar a saída de um comando, escrever isso em algum lugar e também usá-lo como entrada para outro comando?

You can also use tee command to store the output of a command to a file and redirect the same output as an input to another command.

The following command will take a backup of the crontab entries, and pass the crontab entries as an input to sed command which will do the substitution. After the substitution, it will be added as a new cron job.

$ crontab -l | tee crontab-backup.txt | sed 's/old/new/' | crontab –

(crédito para exemplos de uso do comando Tee )

Tee funciona com a filosofia Unix:

Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

(Crédito para Noções básicas sobre a Filosofia Unix )

tee se encaixa em todos eles:

  • faz uma coisa: cria uma cópia extra de entrada
  • funciona com outros programas porque é a cola (ou uma peça de encanamento 'T', se você preferir) que permite que outros programas trabalhem juntos, como nos exemplos acima
  • faz isso manipulando um fluxo de texto dado na entrada padrão
por 10.09.2018 / 13:23
68

It's practically the same and it takes less keyboard hits to type out.

Não é a mesma coisa ...

O seguinte parece ser um pouco equivalente, mas não é:

$ echo "hi" > test.txt
$ echo "hi" | tee test.txt
hi

A diferença crítica é que o primeiro gravou os dados apenas no arquivo nomeado, enquanto o último escreveu hi no terminal ( stdout ) e o arquivo nomeado, conforme mostrado abaixo:

teepermitequevocêgraveosdadosemumarquivoeuse-osemumpipeline,permitindoquevocêfaçacoisasúteis,comomanterosdadosdomeiodocaminhoemumpipeline:

grep'^look'interesting_file.txt\|teeinteresting_lines.txt\|sort

Ou,vocêpodegravaremumarquivocomprivilégioselevados,semconcederprivilégioselevadosaopipelineinteiro(aquiechoéexecutadocomousuário,enquantoteegravanoarquivocomoroot):

echo0\|sudotee/proc/sys/net/ipv4/ip_forward

Comtee,vocêpodegravaremmuitosarquivos(estdout):

echo"hi" \
  | tee a.txt b.txt

Também é possível usar exec com tee para gravar toda a saída de um script em um arquivo, enquanto ainda permite que um observador ( stdout ) veja os dados:

exec > >( tee output.log )
    
por 10.09.2018 / 13:29
25

Este é um tee:

Um encaixe de tubulação em forma de T. Tem uma entrada e duas saídas separadas. Em outras palavras, divide um tubo em dois; como uma bifurcação na estrada.

Da mesma forma, tee é um canal ( | ) que permite redirecionar sua entrada padrão para duas saídas separadas.

Exemplo
Por exemplo, digamos ls / .
Você receberá uma saída parecida com:

Applications    Network     Users       bin        dev      net      private    tmp         var
Library         System      Volumes     cores      etc      home     opt        sbin        usr

Redirecione a saída para um arquivo de texto, ls / > ls.txt , e nenhuma saída será exibida no shell, apenas no arquivo de texto resultante.

Quer ver a saída e passá-la para um arquivo de texto ao mesmo tempo?
Adicione um tee ao seu pipe ( | ), por exemplo: ls / | tee ls.txt

Compare os dois:

ls /          >          ls.txt
ls /        | tee        ls.txt
    
por 11.09.2018 / 18:26
17

Não. Você mencionou um dos poucos exemplos em que você poderia redirecionar para o arquivo usando os operadores > e >> .

Mas o Tee pode fazer muito mais. Porque você canaliza para ele, então você pode canalizar para outra coisa.

Um bom exemplo está listado na página da wikipedia :

find "4DOS" wikipedia.txt | tee 4DOS.txt | sort > 4DOSsorted.txt

Basicamente, você pode canalizar para Tee, então você pode canalizar de Tee para outra coisa. Se tudo que você quer fazer é escrever um arquivo de log, sim, então você realmente não precisa de Tee.

    
por 10.09.2018 / 13:21
16

tee está longe de ser inútil. Eu uso isso o tempo todo e estou feliz que exista. É uma ferramenta muito útil se você tem um pipeline que deseja dividir. Um exemplo muito simples é que você tem algum diretório $d que você quer tar e você também quer hash porque você é paranóico (como eu sou) e não confie no meio de armazenamento para manter os dados de forma confiável. Você poderia gravá-lo no disco primeiro e, em seguida, misturá-lo, mas isso falharia se o arquivo for corrompido antes do hash. Além disso, você teria que lê-lo e se você trabalha em arquivos com várias centenas de GB de tamanho, você saberá que você realmente não quer lê-los novamente se não for necessário.

Então, o que eu faço é simplesmente isto:

tar -c "$d" | tee >(sha256sum) >(cat > "$d"".tar") > /dev/null

Cria a bola de alcatrão e a canaliza para o tee, que a canaliza para duas sub-shells, em uma das quais é hash e na outra é gravada no disco.

Também é ótimo se você deseja realizar várias operações em um arquivo grande:

< file.tar.gz tee >(sha256sum) >(tar -xz) /other/storage/location/file.tar.gz > /dev/null

Lê o arquivo uma vez, o hashes (para que você possa verificar se ainda está como deveria), extrai-o e copia-o para um local diferente. Não há necessidade de ler três vezes por isso.

    
por 10.09.2018 / 17:31
11

Nitpick na resposta de @bertieb que diz Este exemplo mostra o tee sendo usado para ignorar uma limitação inerente no comando sudo. sudo é incapaz de canalizar a saída padrão para um arquivo.

Não há limitação inerente, apenas um mal-entendido de como o comando é processado.

Exemplo:

sudo echo 0 > /proc/sys/net/ipv4/ip_forward

O shell atual analisa a linha de comando. Ele encontra o redirecionamento de saída e executa isso. Em seguida, ele executa o comando, que é o sudo e fornece a linha de comando restante como argumentos para o comando executado. Se o shell atual não tiver permissões de root, o redirecionamento de saída falhará.

echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward

Isso funciona porque o redirecionamento de saída é adiado para o comando tee , que nesse ponto tem permissões de root porque foi executado por meio de sudo .

sudo bash -c "echo 0 > /proc/sys/net/ipv4/ip_forward"

Isso funciona porque o shell que está fazendo o redirecionamento tem permissões de root.

    
por 10.09.2018 / 16:33
9

Como outras pessoas mencionaram, a saída da tubulação para o comando tee grava essa saída em um arquivo e em stdout.

Costumo usar tee quando quero capturar a saída de um comando que leva muito tempo para ser executado, além de querer inspecionar visualmente a saída à medida que o comando a torna disponível. Dessa forma, não preciso esperar que o comando termine de rodar antes de inspecionar a saída.

O que parece não ter sido mencionado ainda (a menos que tenha esquecido), é que o comando tee também pode gravar em vários arquivos de uma só vez. Por exemplo:

ls *.png | tee a.txt b.txt

irá gravar todos os arquivos *.png no diretório atual para dois arquivos diferentes ( a.txt e b.txt ) de uma só vez.

Na verdade, você pode digitar texto em vários arquivos diferentes ao mesmo tempo com tee da seguinte forma:

$ tee --append a.txt b.txt c.txt d.txt
These lines are appended to four different files,
and are also written to stdout.
CTRL-D
    
por 10.09.2018 / 19:22
8

O uso mais comum de tee é ver o texto no terminal ao mesmo tempo em que você o envia ao arquivo (ou arquivos). O texto da sua pergunta supõe que você só escreve texto em arquivos de log. Eu tenho scripts que escrevem listas de nomes de arquivos ou diretórios para acionar arquivos (para serem processados por outros scripts de forma assíncrona) e eu uso tee para enviar o mesmo conteúdo para stdout. Todo stdout é direcionado para os logs. Então eu tenho meu texto onde eu quero e eu tenho uma gravação de entrada de log que eu fiz isso, tudo a partir de uma única declaração 'echo'

tee também é o melhor método no Unix para fazer vários arquivos idênticos. Eu uso isso ocasionalmente para fazer vários arquivos vazios, assim ...

:|tee file01 file02 file03
    
por 10.09.2018 / 16:43
0

Imagine, você quer gravar a saída de um comando em um arquivo de log AND para imprimir no stdout. Quando você precisar fazer isso ao mesmo tempo, precisará de tee .

Um caso de uso é ter scripts de construção que gravam toda a construção no stdout (por exemplo, no Jenkins), mas coisas importantes ao mesmo tempo em um arquivo de log separado (para emails de resumo).

Você realmente começará a perder tee quando precisar criar scripts no Windows. Não há tee e isso é realmente irritante.

    
por 11.09.2018 / 11:35

Tags