Eu tenho um script bash com várias instruções if com base nos argumentos da linha de comando que passo ao chamá-lo. Ter algum tipo de saída sobre quais comandos estão sendo executados é útil para confirmar o fluxo através de todas essas instruções if, mas minha solução atual está me fornecendo muitas informações.
Usando set -v
no script foi um pouco útil para ver os comandos impresso na tela como eles foram executados no script, no entanto eu fico muito muitos comandos. É quase como uma cópia inteira do script.
Quero uma saída que mostre quais comandos estão sendo executados, mas não quero ver comentários, novas linhas, expressões nas instruções if etc.
Existe uma maneira de passar toda a saída possível gerada pela opção -v através de um regex antes de ser impressa? Ou alguma outra solução para que o bash obtenha apenas comandos de saída de um determinado "tipo" (por exemplo, que estejam usando executáveis e não apenas bash declarações específicas, comentários etc.?)
[1] /programming/257616/sudo-changes-path-why foi bastante útil nisso e foi aí que recebi a sugestão para o set -v
uso.
Editar :
Um script semelhante (mas não idêntico) ao que estou executando:
#!/bin/bash
#get verbose command output
set -v
env=$1
if [ "$env" == "dev" ]; then
python ascript.py
fi
if [ "$env" == "prod" ]; then
#launching in prod will most likely fail if not run as root. Warn user if not running as root.
if [ $EUID -ne 0 ]; then
echo "It doesn't look like you're running me as root. This probably won't work. Press any key to continue." > /dev/stderr
read input
fi
#"stop" any existing nginx processes
pkill -f nginx
nginx -c `pwd`/conf/artfndr_nginx.conf
fi
Eu quero apenas 2 conjuntos possíveis de linhas de saída desse script. O primeiro:
python ascript.py
O segundo:
pkill -f nginx
nginx -c /some/current/directory/conf/artfndr_nginx.conf
fonte
set -v
saída você deseja e quais não.Respostas:
Quando escrevo scripts bash mais complexos, uso uma pequena função para executar comandos que também imprimem os comandos executados em um arquivo de log:
Então, no meu script, eu executo comandos como este:
Se você não deseja que um comando seja impresso, execute-o normalmente.
Você pode definir o
$LOG
nome de um arquivo ou apenas removê-lo e imprimir em stdout ou stderr.fonte
v python ascript.py
sem ter que incluir aspas e perder o destaque do código vimeval ..... || ok=1
: irá definir ok para "1" somente quando "eval ..." falhar ?? Talvez você quis dizer "&&"? E se você quis dizer isso, adicione um "ok = 0" antes da linha de avaliação, para que seja "redefinido" a cada vez. Ou simplesmente renomeie "ok" em "erro"? parece que foi o que quis dizer aqui. Então, no final:eval "$@" 2>> "$LOG" && error=0 || error=1
ok
variável que interromperá o script se algum comando falhar. Como isso não era relevante aqui, eu o removi, mas esqueci de excluir o arquivo|| ok=1
. Obrigado, corrigido agora."
rodeia a declaração eval, porque o comando já está cercado por"
sUse um sub-shell, ou seja:
Por exemplo:
impressões
fonte
set -x; cmd; set +x
várias razões. Primeiro, ele não é redefinidoset -x
caso esteja ligado antes. Segundo, o término do script interno não faz com que os traps sejam executados com as configurações detalhadas ativadas.Eu já vi métodos usados semelhantes aos do @ terdon. É o começo do que as linguagens de programação de nível mais alto chamam de registradores e oferecem bibliotecas completas, como log4J (Java), log4Perl (Perl) etc.
Você pode obter algo semelhante usando o
set -x
Bash, como você mencionou, mas pode usá-lo para ativar a depuração apenas um subconjunto de comandos, agrupando blocos de código com eles dessa maneira.Exemplos
Aqui está um padrão de liner que você pode usar.
Você pode agrupá-los dessa maneira para vários comandos em um script.
Log4Bash
A maioria das pessoas não sabe, mas o Bash também possui um log4 *, o Log4Bash . Se você tiver necessidades mais modestas, pode valer a pena configurá-lo.
Exemplos
Aqui estão alguns exemplos de uso do log4bash.
Log4sh
Se você quiser o que eu classificaria como mais do poder total de uma estrutura log4 *, eu tentaria o Log4sh .
excerto
O Log4sh suporta vários shells, não apenas o Bash.
Também foi testado em vários sistemas operacionais, não apenas no Linux.
O uso de uma estrutura log4 * levará algum tempo para aprender, mas vale a pena se você tiver necessidades mais exigentes do seu log. O Log4sh utiliza um arquivo de configuração onde você pode definir anexos e controlar a formatação da saída que será exibida.
Exemplo
Agora, quando eu o executo:
NOTA: O item acima configura o appender como parte do código. Se você gosta disso, pode ser extraído em seu próprio arquivo,
log4sh.properties
etc.Consulte a excelente documentação do Log4sh se precisar de mais detalhes.
fonte
set
comandos que eu precisaria introduzir, alternando entre comentários, etc. todas as linhas "importantes" do script me pareciam mais claras por enquanto. (caractere único porque a função possui um nome de caractere único)echo
em minha própria funçãomecho
e depois passar um switch para o programa chamado-v
verbose quando eu quero desligar as coisas. Também posso controlá-lo com uma segunda opção de argumento que especifica o nome da função, portanto, tenho 2 eixos para controlar o log. Geralmente, esse é o gateway para querer o log4bash.set -x
imprime comandos à medida que são executados. Não imprime comentários.set -x
é prático para depuração (ao contrário doset -v
que não é muito útil). O Zsh possui uma saída melhor doset -x
que o bash, por exemplo, mostra qual função está sendo executada no momento e o número da linha de origem.Você poderia
trap
DEBUG
e depois testar aBASH_COMMAND
variável . Adicione isso ao topo do script:O código é legível; apenas testa se o primeiro argumento começa com
python
oupkill
e o imprime, se for o caso. E a armadilha usaBASH_COMMAND
(que contém o comando que será executado) como o primeiro argumento.Observe que, enquanto
case
usa globs, você pode facilmente:E use expressões regulares.
fonte
Esta é uma versão revisada da função elegante de Steven Penny. Ele imprime seus argumentos em cores e os cita conforme necessário. Use-o para ecoar seletivamente os comandos que você deseja rastrear. Como as aspas são produzidas, você pode copiar as linhas impressas e colá-las no terminal para reexecução imediata enquanto estiver depurando um script. Leia o primeiro comentário para saber o que eu mudei e por quê.
Exemplo de uso com saída:
# xc echo "a b" "c'd" "'" '"' "fg" '' " " "" \# this line prints in green
echo 'a b' c\'d \' '"' fg '' ' ' '' '#' this line prints in green
a b c'd ' " fg # this line prints in green
A segunda linha acima é impressa em verde e pode ser copiada e colada para reproduzir a terceira linha.
Observações adicionais
O xc original de Steven-Penny é inteligente e ele merece todos os créditos por isso. No entanto, notei alguns problemas, mas não pude comentar sua postagem diretamente porque não tenho reputação suficiente. Então, eu fiz uma edição sugerida em sua postagem, mas os revisores rejeitaram minha edição. Por isso, comecei a postar meus comentários como esta resposta, embora eu preferisse poder editar a resposta de Steve Penny.
O que eu mudei Wrt resposta de Steven-Penny
Corrigido: imprimindo cadeias nulas - elas não foram impressas. Corrigido: imprimir seqüências de caracteres que incluem
%
- causaram erros de sintaxe do awk. Substituídofor (j in ...)
porfor (j = 0, ...)
porque o primeiro não garante a ordem de passagem da matriz (depende da implementação do awk). Adicionado 0 aos números octais para portabilidade.Atualizar
Desde então, Steven Penny corrigiu esses problemas em sua resposta; portanto, essas observações permanecem apenas para o registro histórico da minha resposta. Veja a seção Comentários para mais detalhes.
fonte
Você pode usar a função de shell "sh_trace" da biblioteca POSIX stdlib para imprimir o comando em cores antes de executá-lo. Exemplo:
Função Awk subjacente:
fonte