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

10

Eu tenho um script launch.sh que 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

Li a página de depuração bash , mas parece não haver uma opção clara informa se o script original foi iniciado com -x .

    
por Dan Dascalescu 15.07.2014 / 02:35

4 respostas

13

Muitos dos sinalizadores que podem ser passados para bash na linha de comando são set flags. set é o shell embutido que pode alternar esses sinalizadores em tempo de execução. Por exemplo, chamar um script como bash -x foo.sh é basicamente o mesmo que fazer set -x na parte superior do script.

Sabendo que set é o shell embutido responsável por isso nos permite saber onde procurar. Agora podemos fazer help set e 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 informar quais flags 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 um bônus, se você quiser copiar todos os sinalizadores, você também pode fazer

bash -$- /other/script.sh
    
por 15.07.2014 / 03:14
3

set -o produzirá xtrace on se -x for usado, caso contrário xtrace off .

    
por 15.07.2014 / 03:11
2

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

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

Tem a vantagem de ser capaz de rastrear seletivamente (ou de outra forma afetar) apenas o (s) script (s) de que você precisa do comportamento de saída / modificação de - para reduzir a saída externa, etc. O rastreio pode ser desativado para o script de chamada e ainda ser ativado no script chamado. Não é uma proposta de tudo ou nada.

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

Por vezes, defino uma variável como

E=""
E="echo "

ou

E=""
E=": "

e usá-lo (em várias declarações) como

"${E}" rsync ...

ou, apenas para a segunda variação,

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

Então, apenas comento a segunda definição quando quero que o comando seja executado. Você também pode usar essa técnica com um parâmetro ou uma variável exportada.

Com qualquer um desses, você deve ficar atento a declarações compostas, porque o método só funciona na primeira instrução da lista composta.

    
por 19.07.2014 / 00:57
1

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

    
por 15.07.2014 / 03:11