Tentei encontrar uma resposta para esta pergunta, mas não tive sorte até agora:
Eu tenho um script que executa alguns outros scripts, e muitos desses outros scripts têm "set -x", o que os faz imprimir todos os comandos que executam. Gostaria de me livrar disso, mas reter as informações se algum dos scripts enviar a mensagem de erro ao stderr.
Então não posso simplesmente escrever ./script 2>/dev/null
Além disso, não tenho privilégios para editar esses outros scripts, portanto não posso alterar manualmente a opção de configuração.
Eu estava pensando em registrar tudo, desde stderr ao arquivo separado, e filtrar os comandos de rastreamento, mas talvez haja uma maneira mais simples?
./script 2>some_file
Respostas:
Com
bash
4.1 e acima, você pode fazer(também funciona quando
bash
é chamado comosh
).Basicamente, estamos dizendo
bash
para produzir axtrace
saída no descritor de arquivo 7 em vez do padrão 2 e redirecionar esse descritor de arquivo para/dev/null
. O número fd é arbitrário. Use um fd acima de 2 que não seja usado em seu script. Se o shell no qual você está inserindo esse comando forbash
ouyash
, você pode até usar um número acima de 9 (embora possa haver problemas se o descritor de arquivo for usado internamente pelo shell).Se o shell do qual você está chamando esse
bash
script forzsh
, você também pode:para que a variável seja atribuída automaticamente ao primeiro fd livre acima de 9.
Para versões mais antigas de
bash
, outra opção, se a opçãoxtrace
estiver ativada comset -x
(em oposição a#! /bin/bash -x
ouset -o xtrace
), seria redefinirset
como uma função exportada que não faz nada quando aprovada-x
(embora isso interrompa o script se ele (ou qualquer outrobash
script que ele chama) usadoset
para definir os parâmetros posicionais).Gostar:
Outra opção é adicionar uma interceptação DEBUG em um
$BASH_ENV
arquivoset +x
antes de cada comando.Isso não funcionará quando
set -x
for feito em um sub-shell.Como o @ilkkachu disse, desde que você tenha permissão de gravação para qualquer pasta no sistema de arquivos, você deve pelo menos conseguir fazer uma cópia do script e editá-lo.
Se não houver lugar em que você possa escrever uma cópia do script, ou se não for conveniente fazer e editar uma nova cópia sempre que houver uma atualização no script original, você ainda poderá:
Isso (e a abordagem de cópia) pode não funcionar corretamente se o script faz algo sofisticado
$0
ou variáveis especiais como$BASH_SOURCE
(como procurar arquivos que sejam relativos ao local do próprio script), portanto, talvez seja necessário editar mais, como substitua$0
pelo caminho do script ...fonte
{BASH_XTRACEFD}>
truque também funciona embash
4.1 ou posterior.ksh93
oubash
em que a variável não é passado no ambiente do comando (compare<shell> -c 'export fd; printenv fd {fd}> /dev/null'
emzsh
,bash
eksh93
). Você poderia fazê-lo funcionar emksh93
/bash
fazendo isso em duas etapas ou possivelmente usandoeval
, masbash
, para isso, teria efeitos colaterais se a opção xtrace estivesse ativada.Como são scripts, você pode fazer cópias deles e editá-los.
Fora isso, filtrar a saída parece simples, você pode definir explicitamente
PS4
algo mais incomum que uma única vantagem, para facilitar a filtragem:(é claro que isso entrará em colapso stdout e stdin, mas a tubulação apenas stderr no Bash fica meio peluda, então eu vou ignorar isso)
fonte
PS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%')
.bash
problemas comogrep
é executado de forma assíncrona (o bash não está esperando por isso, para que ele possa (e geralmente o faça) emitir coisas após o início do próximo comando no script).