AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 766406
Accepted
Seamus
Seamus
Asked: 2024-01-08 15:26:39 +0800 CST2024-01-08 15:26:39 +0800 CST 2024-01-08 15:26:39 +0800 CST

Criando uma opção para 'exec > >(tee -ia $OUT)' para pular stdout

  • 772

Estou tentando modificar um script que usa o seguinte:

# first portion of script
# ...
exec > >(tee -ia $OUT)
# ...
# second portion of script 

O problema que tenho com este script é que ele produz uma saída volumosa para stdout(meu terminal). O autor do script não incluiu opções para eliminar a saída do terminal. Gostaria de adicionar uma opção que remova o stdoute obtenha a saída somente no arquivo $OUT.

Aqui está o que eu tentei:

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else {

# ...
# second portion of script 

} > $OUT
fi

Isso parece funcionar, mas não tenho certeza sobre o uso de chaves {} neste contexto, pois a seção GNU de Comandos de agrupamento ( parece ) afirma que ;é necessário um ponto-e-vírgula após a lista. Mas adicionar ;ou deixar de lado parece não fazer diferença. Eu me perguntei se deveria usar parênteses ()em vez de chaves, mas isso faz com que tudo dentro do ()seja executado em um subshell. Não estou particularmente interessado nisso, pois é o script de outra pessoa e as implicações do subshell não são claras para mim (não tentei isso).

A outra coisa que tentei parecia um hack, mas li sobre outras pessoas que o usaram e parece funcionar bem também:

TERM_OPT="OFF"

# first portion of script
# ...

if [ $TERM_OPT != "OFF" ]; then
     exec > >(tee -ia $OUT)
else
     exec > >(tee -ia $OUT 1> /dev/null)
fi

# ...
# second portion of script 

Eu gosto disso porque parece mais independente , mas isso não é uma consideração importante AFAICT.

Portanto, a questão é: Qual é a maneira correta de fazer isso? Com isso, quero dizer qual é a maneira correta de cancelar a saída do terminal após um exec > >(tee -ia $OUT)? Uma dessas soluções é preferível à outra - ou preciso fazer algo completamente diferente?

bash
  • 2 2 respostas
  • 29 Views

2 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-01-08T15:57:41+08:002024-01-08T15:57:41+08:00

    Apenas redirecionar para o $OUTarquivo no amodo ppend é muito mais fácil:

    case $TERM_OPT in
      (OFF) exec >> "$OUT";;
      (*)   exec > >(tee -ia -- "$OUT")
    esac
    

    Cuidado, o shell não espera teeao sair, então você pode descobrir que teeainda está gerando algo após a conclusão do script.

    $ bash -c 'exec > >(tee -ia -- file); echo A'; echo B; sleep 1
    B
    A
    

    Veja como Afoi a saída após B.

    Para contornar isso, você pode adicionar:

    if [ "$TERM_OPT" != OFF ]; then
      exec > /dev/null # closes the pipe to tee which should cause tee
                       # to see EOF on input and exit
      wait # waits for all asynchronous tasks including tee
    fi
    

    No final do roteiro ou em uma EXITarmadilha.

    Outra opção (que também funcionaria em sh) é colocar todo o seu script dentro de uma mainfunção e fazer:

    #! /bin/sh -
    main() {
      # your script here
    }
    case $TERM_OPT in
      (OFF) main "$@" >> "$OUT";;
      (*)   main "$@" | tee -ia -- "$OUT"
    esac
    
    • 3
  2. ilkkachu
    2024-01-08T15:58:19+08:002024-01-08T15:58:19+08:00

    Se você deseja redirecionar o stdout para ser anexado a um arquivo, e também não ter uma cópia da saída no terminal, basta fazer:

    exec >> "$OUT"
    

    O único propósito teeé duplicar um fluxo em vários, portanto, se você deseja a saída apenas em um local, não há necessidade disso. É claro que você tee -ia "$OUT" > /dev/nulltambém funcionaria, mas isso é um pouco bobo: você ainda estaria duplicando a saída, apenas para descartar a outra cópia.

    Não tenho certeza sobre o uso de chaves {}neste contexto

    As chaves requerem um ponto e vírgula ou uma nova linha. Na verdade, diz isso no manual: "O ponto e vírgula (ou nova linha) da lista a seguir é obrigatório." Os parênteses não exigem nenhum dos dois.

    As implicações de um subshell são que o subshell é executado em uma cópia independente do shell e quaisquer alterações no subshell não são visíveis fora dele. Se o script terminar de qualquer maneira quando o subshell terminar, isso não significa muito, e tudo o que o subshell faz é iniciar um processo desnecessário.

    Eu iria com algo como

    if [ "$TERM_OPT" != "OFF" ]; then
         exec > >(tee -ia -- "$OUT")
    else
         exec >> "$OUT"
    fi
    
    • 2

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve