Qual é o propósito de 'tee'?

90

Todos os usos que teeeu já vi eram tais:

 do_something | tee -a logfile

Ou:

do_something_else | tee logfile

Foi teeinventado para aqueles que não sabem que você pode fazer o mesmo com redirecionamentos de pipe de shell? Tal como:

do_something >> logfile

Ou:

do_something_else > logfile

É praticamente o mesmo e são necessários menos toques no teclado para digitar. Em quais recursos ocultos não estou vendo tee?

R Moog
fonte
62
Como isso não foi respondido pela primeira linha da página de manual "... e gravada na saída e nos arquivos padrão" ? As respostas são interessantes, mas falar amplamente sobre como os tubos são úteis apenas reforça como esse Q parece muito amplo e talvez devesse ter sido fechado.
Xen2050 12/09
3
@ Xen2050 Não é possível culpar uma pergunta por uma resposta muito ampla. A pergunta é muito específica, assim como a resposta atual com a classificação mais alta .
Jon Bentley
1
@ JonBentley a pergunta não soa como "um problema específico com detalhes suficientes para identificar uma resposta adequada" (conforme a caixa de diálogo fechar). Parece o seguinte: "se sua pergunta puder ser respondida por um livro inteiro ou tiver muitas respostas válidas (mas não há como determinar quais - se houver alguma) estão corretas -, provavelmente é muito amplo para o nosso formato". (Fonte: Central de Ajuda )
Xen2050 15/09/18
4
@ Xen2050 Estamos lendo a mesma pergunta? Parece altamente específico para mim - qual é a diferença entre tee e pipes? Foi respondido adequadamente usando duas frases. Longe de um livro inteiro. O fato de algumas respostas optarem por uma tangente não tem nada a ver com o escopo da pergunta.
Jon Bentley
@ JonBentley: Estamos lendo a mesma pergunta? R Moog meio que implica uma pergunta bastante bem focada - qual é a diferença entre tee e o redirecionamento de E / S ?   O fato de dizer “ redirecionamentos de pipe de shell como e ” não é um ponto a seu favor e é um argumento para o fechamento como pouco claro. Mas, na verdade, ele faz várias perguntas: “Qual é o objetivo ?”, “Foi inventado para aqueles que não sabem que você pode fazer o mesmo com os redirecionamentos de pipe de shell?” E “Em quais recursos ocultos não estou vendo ?”. Pelo menos duas dessas perguntas são muito amplas. >>>teeteetee
G-Man

Respostas:

242

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

O objetivo teeé produzir um cenário de múltiplas entradas e uma entrada - exatamente como em um cruzamento em 'T'.

EDITAR

Houve comentários em torno de como teepossibilita o uso mais aparente de sudo. Isso não vem ao caso: cat, ddou talvez seja melhor bufferoferecer esta possibilidade com melhor desempenho, se você não precisa as várias saídas. Use teepara o que foi projetado, não para o que "também pode fazer"

Eugen Rieck
fonte
37
Saída múltipla é a chave. teepode até aceitar vários argumentos e gravar em muitos arquivos de uma só vez.
Kamil Maciorowski
20
Eu chamaria isso de encaixe de tubo em T , não uma travessia (como no cruzamento de uma estrada?).
User20574 11/1118
7
Como eu usaria de catmaneira direta em vez de teepor exemplo echo /var/work/core.%p | sudo tee /proc/sys/kernel/core_pattern? echo /var/work/core.%p | sudo cat > /proc/sys/kernel/core_patternnão funciona, porque o redirecionamento é processado pelo shell não sudo. Quanto a dd, echo /var/work/core.%p | sudo dd of=/proc/sys/kernel/core_patternfunciona, mas ddmuitas vezes é uma ferramenta sobrecarregada, capaz de causar grandes danos, especialmente sob sudo. Quanto buffer, não é instalado por padrão em qualquer uma das distros baseadas no Ubuntu RedHat- ou eu tenho que entregar (ou MacOS) ...
Digital Trauma
3
@EugenRieck Eu entendo o seu ponto de vista sobre a relação 1: n entre in: out sendo a função principal. No entanto, nem o construído catnem o /bin/cattrabalho para mim nesta situação. Não importa de onde catvem - o >ainda será tratado pelo shell de nível superior (não sudo). A vantagem de teemais catnesta situação é que ele permite que o arquivo de saída para ser passado como um parâmetro de linha de comando (e não um redirecionamento). ddé certamente uma opção viável, embora eu ainda prefira teeisso #
Digital Trauma
3
@EugenRieck Que shell tem cate teecomo builtins? E qual versão do sudopode executar shell builtins?
Wjandrea
118

Tee não é inútil

Talvez você soubesse disso, afinal? Se não, continue a ler! Ou se você sabe como funciona, mas não sabe ao certo por que existe, pule para o final para ver como ele se encaixa na filosofia do Unix.

Qual é o propósito tee?

Na sua forma mais simples, coleta dados na entrada padrão e grava-os na saída padrão e em um (ou mais) arquivos. Foi comparado a uma peça de T 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 do_somethinge a anexa ao arquivo de log, enquanto também a exibe ao usuário. De fato, a páginatee da Wikipedia apresenta esse como o segundo exemplo:

Para visualizar e anexar a saída de um comando a um arquivo existente:

  lint program.c | tee -a program.lint

Isso exibe a saída padrão do comando lint program.c no computador e, ao mesmo tempo, anexa uma cópia ao final do arquivo program.lint. Se o arquivo program.lint não existir, ele será criado.

O exemplo a seguir tem outro uso: escalação de permissões :

Para permitir o escalonamento de permissões:

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

Este exemplo mostra tee sendo usado para ignorar uma limitação inerente no sudocomando. sudonão consegue canalizar a saída padrão para um arquivo. Ao despejar seu fluxo de saída padrão /dev/null, também suprimimos a saída espelhada no console. O comando acima fornece ao usuário root acesso atual a um servidor através de ssh, instalando a chave pública do usuário na lista de autorização de chave do servidor.

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?

Você também pode usar o comando tee para armazenar a saída de um comando em um arquivo e redirecionar a mesma saída que uma entrada para outro comando.

O comando a seguir fará um backup das entradas do crontab e passará as entradas do crontab como uma entrada para o comando sed que fará a substituição. Após a substituição, ele será adicionado como um novo trabalho cron.

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

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

Tee trabalha com a filosofia Unix:

Escreva programas que fazem uma coisa e fazem bem. Escreva programas para trabalhar juntos. Escreva programas para lidar com fluxos de texto, porque essa é uma interface universal.

(Crédito ao básico da filosofia Unix )

tee serve para todos:

  • faz uma coisa: cria uma cópia extra da entrada
  • ele funciona com outros programas porque é a cola (ou uma peça de encanamento em 'T', se você preferir) que permite que outros programas funcionem juntos, como nos exemplos acima
  • isso é feito através da manipulação de um fluxo de texto fornecido na entrada padrão
bertieb
fonte
3
@ Joe: sudo tee -aé provavelmente uma inovação mais recente (eu a vi pela primeira vez nos guias / wikis do Ubuntu, especialmente para definir coisas /proc/sys, porque a mudança para o Ubuntu ocorreu quando eu mudei para um sudosistema baseado (como o Ubuntu é configurado por padrão) em vez de usar sucom um senha root). Eu acho que teeé anterior sudo, então não é uma razão para teeexistir. Você não precisa teedisso, é simplesmente mais curto para digitar interativamente sudo sh -c 'cat > output'.
Peter Cordes
1
Com conchas modernas como bash, você pode teealimentar dois gasodutos, como foo | tee >(pipe2) | pipe1. Ou outro divertido é ffmpeg ... |& tee /dev/tty | sed 's/.*\r// > encode.logver as atualizações da linha de status interativamente no tty, enquanto remove as "linhas" que terminam com retorno de carro em vez de nova linha para o log real. (ou seja, filtre as atualizações da linha de status). Em geral, você pode colar um local tee /dev/ttyem qualquer lugar no pipeline como uma impressão de depuração.
Peter Cordes
2
É menos uma limitação do sudo com a qual você está trabalhando e mais uma limitação da interpretação do> do shell. Quando você executa um comando com sudo, o stdout é enviado de volta ao seu programa shell e os redirecionamentos adicionais com> são executados com as permissões do shell. Se você deseja gravar com permissões elevadas, é necessário que a parte elevada do pipeline seja o que está escrito. Existem várias maneiras de fazer isso, dependendo exatamente de qual efeito você está buscando. Se você realmente quiser usar> algo como 'sudo bash -c "command> outfile"' fará o trabalho.
Perkins
Exatamente, @Perkins. O shell analisa >e configura o redirecionamento antes que o sudo seja obtido exec, então definitivamente não é uma limitação do sudo que ele não lida com coisas que nunca vê. :) Normalmente, tento me referir a isso como "o fluxo de trabalho do sudo" ou algum termo semelhante ao explicá-lo, em vez de descrever o próprio sudo.
dannysauer
sudo tee -aIMHO é um abuso de tee. Use sudo cat, sudo ddou (com melhor desempenho em muitos casos) sudo bufferse você não precisa as várias saídas.
Eugen Rieck 14/09
70

É praticamente o mesmo e são necessários menos toques no teclado para digitar.

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 gravou hino terminal ( stdout) e no arquivo nomeado, conforme mostrado abaixo:

redirecionar vs tee


teepermite gravar os dados em um arquivo e usá-los em um pipeline posterior, permitindo que você faça coisas úteis - como impedir que os dados parem no meio de um pipeline:

grep '^look ' interesting_file.txt \
  | tee interesting_lines.txt \
  | sort

Ou, você pode gravar em um arquivo com privilégios elevados, sem conceder privilégios elevados a todo o pipeline (aqui echoé executado como usuário, enquanto teegrava no arquivo como root):

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

Com tee, você pode gravar em muitos arquivos ( e stdout ):

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

Também é possível usar execcom teepara 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 )
Attie
fonte
2
Não se esqueça exec > >(tee "$LOGFILE") 2>&1de um script bash que permite que o script produza stdout e stderr para ambos, stdout e o arquivo apontado por $LOGFILE.
Rexkogitans
@rexkogitans 2> & 1 não é essa sintaxe do lote do cmd?
dmb 10/09/18
@dmb: É sintaxe shell para "enviar stderr (= 2) para o mesmo lugar como stdout (= 1)"
psmears
@rexkogitans Foi realmente uma pergunta justa, não sei se você não usa o "Windoze" há uma década. Eu uso 2>&1para soltar a saída e errar para arquivos txt no Windows.
dmb 10/09/18
1
@mbmb Desculpe por parecer rude. É tudo sobre o comentário dos psmears. Obviamente, o Windows adotou o estilo Unix aqui.
Rexkogitans
27

Este é um tee:
insira a descrição da imagem aqui

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

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


Exemplo
Digamos, por exemplo, que você digite ls /.
Você obterá 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.txte nenhuma saída será exibida no shell, apenas no arquivo de texto resultante.

Deseja ver a saída E transmiti-la para um arquivo de texto ao mesmo tempo?
Adicione a teeao seu pipe ( |) ou seja:ls / | tee ls.txt


Compare os dois:

ls /          >          ls.txt
ls /        | tee        ls.txt
tjt263
fonte
4
+1 para o retrato que como sabemos vale por mil palavras
Sergiy Kolodyazhnyy
Se você tivesse escolhido um pedaço T de mangueira de jardim, estaria alinhado com a metáfora original de Doug McIlroy.
JdeBP
@JdeBP Desculpe, eu não tenho idéia de quem é. Ele é o autor original do utilitário ou algo assim? O fluxo de dados e a corrente elétrica física são frequentemente comparados aos sistemas hidráulicos, mas você provavelmente sabe disso. Enfim, eu apenas escolhi esse estilo para mantê-lo super simples. Na verdade, eu faria isso para mantê-lo familiar, mas a variedade de jardins tende a ter um formato mais Y e / ou acessórios visualmente complicados para prender acessórios etc. É basicamente o mesmo.
precisa saber é o seguinte
18

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

Mas Tee pode fazer muito mais. Como você usa isso, pode usar outro método.

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, para que possa passar de Tee para outra coisa. Se tudo o que você quer fazer é escrever um arquivo de log, sim, então você realmente não precisa do Tee.

LPChip
fonte
17

teeestá longe de ser inútil. Eu uso o tempo todo e fico feliz que ele exista. É uma ferramenta muito útil se você tiver um pipeline que deseja dividir. Um exemplo muito simples é que você tem algum diretório $dque deseja tar e também o quer fazer hash porque é paranóico (como eu sou) e não confia no meio de armazenamento para armazenar os dados de maneira confiável. Você pode gravá-lo primeiro no disco e depois fazer o hash, mas isso falharia se o arquivo fosse corrompido antes de ser hash. Além disso, você precisaria lê-lo e se trabalhar com arquivos com várias centenas de GB de tamanho, saberá que realmente não deseja lê-los novamente, se não for necessário.

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

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

Ele cria a bola de alcatrão e a conduz ao tee, o que a leva a duas subcascas, em uma das quais é hash e na outra, gravada no disco.

Também é ótimo se você deseja executar 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, faz o hash (para que você possa verificar se ainda está como deveria estar), extrai-o e copia-o para um local diferente. Não é necessário ler três vezes para isso.

UTF-8
fonte
3
Nitpick: teenão cria os subshells; O chamado é executado shell sha5sume cate se conecta a sua saída para o arquivo descritores que são passados para tee. Além disso, um uso inútil de cat; você pode usar o redirecionamento de entrada para ter teelido diretamente file.tar.gz.
chepner
@chepner Você está certo sobre a primeira interjeição, mas está completamente errado sobre a segunda. Eu gosto de escrever meus pipelines em ordem, portanto, denotar a entrada à direita é terrível para facilitar a leitura, e é claramente objetivamente inferior ao meu método e totalmente não é uma preferência subjetiva minha. caté amor. caté vida.
UTF-8
6
Você também pode escrever < file.tar.gz tee >(sha256sum) ...se estiver preocupado com a ordem lexical dos redirecionamentos. Isso não muda o fato de que não há necessidade de um processo totalmente separado apenas para alimentar um único arquivo tee.
chepner
1
@chepner Legal, obrigado! Aprendi algo hoje. :)
UTF-8
1
O custo de partida cat é relativamente baixo. O custo de 100 GiB extras de chamadas do sistema write + read definitivamente desperdiça tempo extra da CPU e largura de banda da memória para o exemplo proposto de um arquivo enorme. Lembre-se de que a largura de banda da memória é um recurso compartilhado em todos os núcleos, sem mencionar a poluição extra do cache L3 dessa cópia. Em um x86 com a mitigação Spectre + Meltdown ativada, as chamadas do sistema são mais caras do que costumavam ser. Você está gastando uma quantidade mensurável de tempo extra da CPU ao longo dessa cópia. Também >(cat > foo)não é mais fácil entender do que fooIMO.
Peter Cordes
12

Nitpick na resposta de @ bertieb que diz Este exemplo mostra tee sendo usado para ignorar uma limitação inerente no comando sudo. O sudo não pode 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 sudoe 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 teecomando, que nesse momento possui permissões de root porque foi executado via sudo.

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

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

studog
fonte
2
Além disso, pode ser necessário sudopara o comando, mas não para o arquivo a ser emitidos e o redirecionamento funciona muito bem:sudo foo-needs-privilege > /tmp/this-output-file-doesnt
Dennis Williamson
10

Como outras pessoas mencionaram, canalizar a saída para o teecomando grava essa saída em um arquivo e em stdout.

Costumo usar teequando quero capturar a saída de um comando que leva muito tempo para ser executado, enquanto também quero inspecionar visualmente a saída à medida que o comando a disponibiliza. Dessa forma, não preciso esperar que o comando termine de executar antes de inspecionar a saída.

O que parece não ter sido mencionado ainda (a menos que eu tenha perdido), é que o teecomando também pode gravar em vários arquivos ao mesmo tempo. Por exemplo:

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

gravará todos os *.pngarquivos no diretório atual em dois arquivos diferentes ( a.txte b.txt) ao mesmo tempo.

Na verdade, você pode digitar texto em vários arquivos diferentes ao mesmo tempo, com o teeseguinte:

$ 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
JL
fonte
9

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

tee também é o melhor método no Unix para criar vários arquivos idênticos. Eu uso ocasionalmente para criar vários arquivos vazios, como este ...

:|tee file01 file02 file03
Wil Young
fonte
5
por que não touch? (mais imediatamente óbvio o que está acontecendo)
Attie
O @Attie touchnão truncará os arquivos se eles já existirem, mas apenas atualizará seus carimbos de data e hora e deixará o conteúdo como está; mas teeirá truncá-los. Além disso, fazendo rm+ touché diferente tee(pense sobre hardlinks e links simbólicos)
Matija Nalis
Então porque não truncate -s 0? :-)
Attie
1

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

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

Você realmente começará a faltar teequando precisar fazer um script no Windows. Não existe teee isso é realmente irritante.

domih
fonte
Não é trivial criar?
Lightness Races in Orbit
Não é possível com lote / cmd, pois você não pode dividir um fluxo de saída de um comando facilmente.
domih 12/09/18
Certo, mas como um programa de três-line C ++ ...
Leveza raças na órbita
1
A distribuição Windows unxutils possui muitas ferramentas de linha de comando Unix que, diferentemente de algumas distribuições, não poluem o ambiente de execução do Windows. A maior limitação está no "glob" bing, que funciona de maneira diferente no Unix / Linux e no Windows. "tee" está entre as ferramentas disponíveis.
cmm
2
Não seja bobo, é 2018. Use o PowerShell, ele tem tee. O Cmd nunca foi destinado a scripts sérios - era para isso que o VBS era. O Powershell é a nova ferramenta de script essencial. É verdade que o Cmd ainda é bastante poderoso, mas as ferramentas de linha de comando são muito poucas.
Luaan 13/09/18