Como posso saber se o script bash atualmente em execução foi chamado com -x para depuração?

11

Eu tenho um script launch.shque se executa como outro usuário para criar arquivos com o proprietário correto. Eu quero passar -x para esta invocação se ela foi originalmente passada para o script

if [ `whoami` == "deployuser" ]; then
  ... bunch of commands that need files to be created as deployuser
else
  echo "Respawning myself as the deployment user... #Inception"
  echo "Called with: <$BASH_ARGV>, <$BASH_EXECUTION_STRING>, <$->"
  sudo -u deployuser -H bash $0 "$@"  # How to pass -x here if it was passed to the script initially?
fi

Eu li a página de depuração do bash, mas parece não haver uma opção clara que indique se o script original foi iniciado com -x.

Dan Dascalescu
fonte

Respostas:

15

Muitos dos sinalizadores que podem ser passados bashna linha de comando são setsinalizadores. seté o shell interno que pode alternar esses sinalizadores em tempo de execução. Por exemplo, chamar um script como bash -x foo.shbasicamente é o mesmo que fazer set -xna parte superior do script.

Saber que seté o shell interno responsável por isso nos permite saber onde procurar. Agora podemos fazer help sete obtemos o seguinte:

$ help set
set: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
...
      -x  Print commands and their arguments as they are executed.
...
    Using + rather than - causes these flags to be turned off.  The
    flags can also be used upon invocation of the shell.  The current
    set of flags may be found in $-.  The remaining n ARGs are positional
    parameters and are assigned, in order, to $1, $2, .. $n.  If no
    ARGs are given, all shell variables are printed.
...

Então, a partir disso, vemos que $-deve nos dizer quais sinalizadores estão ativados.

$ bash -c 'echo $-'
hBc

$ bash -x -c 'echo $-'
+ echo hxBc
hxBc

Então, basicamente, você só precisa fazer:

if [[ "$-" = *"x"* ]]; then
  echo '`-x` is set'
else
  echo '`-x` is not set'
fi

Como bônus, se você deseja copiar todas as bandeiras, também pode fazer

bash -$- /other/script.sh
Patrick
fonte
1
Você precisará usar [[ $- == *x* ]]para a correspondência de padrões.
Glenn Jackman
1
Ou você pode usar o padrão case $- in *x*) ... ;; *) ... ;; esac. É útil conhecer esse uso de casescripts que devem ser portáteis e, agora que eu o conheço, acho mais fácil lembrar disso, do que lembrar "se for específico do bash, então [[, mais case".
Hvd
OK, toda essa série de comentários pode ser excluída.
L0b0
$-saídas hB. O que o -he -Bbandeiras / argumentos fazer? Não o veja na página do manual do bash .
Dan Dascalescu
3

set -oproduzirá xtrace onse -xfor usado, caso contrário xtrace off.

vinc17
fonte
2

Embora a resposta do @Patrick seja a "correta", você também pode simplesmente passar um parâmetro ou variável exportada para o script filho que diz o que fazer - como ativar o rastreamento.

Isso tem a desvantagem de que (acredito) você precise reexportá-lo para cada nível de script que está prestes a inserir.

Tem a vantagem de ser capaz de rastrear seletivamente (ou afetar de outra forma) apenas os scripts dos quais você precisa do comportamento de saída / modificado - para reduzir a saída estranha, etc. ainda será ativado no script chamado. Não é uma proposta de tudo ou nada.

Não faz parte da sua pergunta, mas está relacionado:

Às vezes eu defino uma variável como

E=""
E="echo "

ou

E=""
E=": "

e use-o (em várias instruções) como

"${E}" rsync ...

ou, apenas para a segunda variação,

"${E}" echo "this is a debugging message"

Depois, apenas comento a segunda definição quando quero que os comandos sejam executados. Você também pode usar esta técnica com um parâmetro ou variável exportada.

Com qualquer um desses itens, é necessário observar as instruções compostas, pois é garantido que o método funcione apenas na primeira instrução da lista composta.

Joe
fonte
1

Você pode pegar o PID do processo e, em seguida, examinar a tabela de processos com ps para ver quais eram os argumentos.

Paul Calabro
fonte
Você pode pegar o processo 'PID via: $$
Paul Calabro
2
Eu não acho que seja uma boa ideia em geral, porque se o -xfoi definido dentro do script, não será mostrado na pssaída. E esta solução é ineficiente de qualquer maneira.
vinc17
Esse é um argumento justo. Na verdade, eu não sabia sobre a variável $ -. Essa parece ser uma abordagem muito melhor para resolver isso.
Paul Calabro
1
Há também a set -osolução que propus. Também deve funcionar para opções que não possuem um sinalizador associado como -x.
vinc17