Estou criando um script de uma estrutura de teste no bash e estou me deparando com uma situação estranha.
Algumas coisas que estou fazendo nesta postagem para fins ilustrativos:
- Adicionando
echo
linhas aos scripts; estes não fazem parte do conjunto de testes. - Executando todos os scripts em janelas de terminal com mais de 80 caracteres
- A execução de todos os scripts dos diretórios em que residem, por meio, por exemplo, de
./test1
.
Primeiro, há um setup
script. Isso source
vem dos próprios scripts de teste (não pode ser executado em um subshell porque precisa definir variáveis de ambiente). O primeiro corte fica assim.
# Make output consistent regardless of width of terminal running the script.
export COLUMNS=80
echo setup: $COLUMNS
O script test1
é assim.
#!/bin/bash
# Send output to both the screen and a file.
exec > >(tee logfile)
echo before: $COLUMNS
. ./setup
echo after: $COLUMNS
Executar test1
dá os resultados esperados.
before:
setup: 80
after: 80
Adicionar uma linha para setup
bagunçar tudo, no entanto.
# Make output consistent regardless of width of terminal running the script.
export COLUMNS=80
echo setup: $COLUMNS
date
echo setup 2: $COLUMNS
Agora a saída da execução test1
é:
before:
setup: 80
Tue Jul 2 13:36:43 CDT 2024
setup 2: 232
after: 232
Isso é explicado pela checkwinsize
opção bash. Como a página de manual documenta esta opção: "Se definido, o bash verifica o tamanho da janela após cada comando externo (não integrado) e, se necessário, atualiza os valores de LINHAS e COLUNAS. Esta opção é habilitada por padrão." export
e echo
não são comandos externos, mas date
são, e é por isso que chamá-los anula o $COLUMNS
valor definido explicitamente.
A próxima estranheza surge quando outro script de teste, test2
tem requisitos de log diferentes e envia stdout e stderr para logfile
.
$ diff test1 test2
3c3
< exec > >(tee logfile)
---
> exec > >(tee logfile) 2>&1
Correr test2
produz isto:
before:
setup: 80
Tue Jul 2 13:46:20 CDT 2024
setup 2: 80
after: 80
Por que isso anularia a checkwinsize
opção?
A setup
desativação checkwinsize
resolve meu problema prático, que é fazer com que todos os scripts de teste respeitem o $COLUMNS
valor definido explicitamente. Mas ainda estou intrigado com o motivo pelo qual a adição de 2>&1
altera tanto o comportamento. É este o resultado pretendido?
Estou vendo isso no bash versão 5.0.18(1). Eu sei que isso é um pouco antigo e estaria interessado em saber se o comportamento é o mesmo em uma festa mais recente.
Não é o mesmo em um ainda mais antigo ao qual tenho acesso (versão 3.2.57(1)) - curiosamente, a diferença aqui é que a date
invocação não é redefinida $COLUMNS
para a largura do terminal, apesar da página de manual desta versão documentar checkwinsize
essencialmente de forma idêntica . Portanto, esta versão parece ter bugs, pois seu comportamento não corresponde à documentação.
No seu cenário, o Bash recupera o tamanho da “janela” do terminal associado ao seu erro padrão, se houver. Redirecionar o erro padrão significa que ele não pode fazer isso, portanto
COLUMNS
permanece inalterado mesmo secheckwinsize
estiver ativado.Não acho que isso esteja documentado, mas você pode ver no código-fonte . As referências a
input_tty
são um tanto enganosas: é umshell_tty
erro padrão ou . Em shells não interativos,shell_tty
não está definido ou corresponde ao erro padrão.