Wie kann ich feststellen, ob das aktuell ausgeführte Bash-Skript mit -x zum Debuggen aufgerufen wurde?

11

Ich habe ein Skript launch.sh, das sich selbst als ein anderer Benutzer ausführt, um Dateien mit dem richtigen Eigentümer zu erstellen. Ich möchte -x an diesen Aufruf übergeben, wenn er ursprünglich an das Skript übergeben wurde

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

Ich habe die Bash-Debugging-Seite gelesen, aber es scheint keine eindeutige Option zu geben, die angibt, ob das ursprüngliche Skript mit gestartet wurde -x.

Dan Dascalescu
quelle

Antworten:

14

Viele der Flags, die in bashder Befehlszeile übergeben werden können, sind setFlags. setist die integrierte Shell, mit der diese Flags zur Laufzeit umgeschaltet werden können. Zum Beispiel ist das Aufrufen eines Skripts im bash -x foo.shGrunde dasselbe wie set -xoben im Skript.

Wenn setwir wissen, dass die Shell dafür verantwortlich ist, wissen wir, wo wir suchen müssen. Jetzt können help setwir Folgendes tun und erhalten Folgendes:

$ 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.
...

Daraus ergibt sich, dass wir wissen $-sollten, welche Flags aktiviert sind.

$ bash -c 'echo $-'
hBc

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

Im Grunde müssen Sie nur Folgendes tun:

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

Als Bonus können Sie auch alle Flags kopieren

bash -$- /other/script.sh
Patrick
quelle
1
Sie müssen [[ $- == *x* ]]für den Mustervergleich verwenden.
Glenn Jackman
1
Oder Sie könnten den Standard verwenden case $- in *x*) ... ;; *) ... ;; esac. Es ist nützlich, diese Verwendung casefür Skripte zu kennen , die portabel sein sollen, und jetzt, da ich davon weiß, fällt es mir leichter, mich nur daran zu erinnern, als sich daran zu erinnern, "wenn bash-spezifisch, dann [[sonst case".
DVD
OK, dann könnte diese ganze Reihe von Kommentaren gelöscht werden.
10b0
$-Ausgänge hB. Was machen die -hund -BFlags / Argumente? Sehen Sie dann nicht in der Bash-Manpage .
Dan Dascalescu
3

set -owird ausgegeben, xtrace onwenn -xandernfalls verwendet wird xtrace off.

vinc17
quelle
2

Obwohl die Antwort von @Patrick die "richtige" ist, können Sie auch einfach einen Parameter oder eine exportierte Variable an Ihr untergeordnetes Skript übergeben, die ihm sagt, was zu tun ist - wie das Aktivieren der Ablaufverfolgung.

Dies hat den Nachteil, dass Sie es (glaube ich) erneut in jede Skriptebene exportieren müssen, die Sie eingeben möchten.

Es hat den Vorteil, dass nur die Skripte, von denen Sie die Ausgabe / das geänderte Verhalten benötigen, selektiv verfolgt (oder anderweitig beeinflusst) werden können, um die externe Ausgabe usw. zu reduzieren. Beispielsweise kann die Ablaufverfolgung für das aufrufende Skript und deaktiviert sein werde immer noch im aufgerufenen Skript eingeschaltet. Es ist nicht alles oder nichts.

Nicht Teil Ihrer Frage, aber verwandt:

Ich definiere manchmal eine Variable wie

E=""
E="echo "

oder

E=""
E=": "

und benutze es (in mehreren Aussagen) wie

"${E}" rsync ...

oder, nur für die zweite Variante,

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

Dann kommentiere ich einfach die zweite Definition aus, wenn die Befehle ausgeführt werden sollen. Sie können diese Technik stattdessen auch mit einem Parameter oder einer exportierten Variablen verwenden.

Bei beiden müssen Sie auf zusammengesetzte Anweisungen achten, da die Methode garantiert nur für die erste Anweisung in der zusammengesetzten Liste funktioniert.

Joe
quelle
1

Sie können die PID des Prozesses abrufen und dann die Prozesstabelle mit ps untersuchen, um festzustellen, welche Argumente sie haben.

Paul Calabro
quelle
Sie können den Prozess 'PID über: $$
Paul Calabro
2
Ich denke nicht, dass dies im Allgemeinen eine gute Idee ist, denn wenn das -xim Skript festgelegt wurde, wird es nicht in der psAusgabe angezeigt . Und diese Lösung ist sowieso ineffizient.
vinc17
Das ist ein faires Argument. Ich wusste eigentlich nichts über die Variable $ -. Das scheint ein viel besserer Ansatz zu sein, um dies zu lösen.
Paul Calabro
1
Es gibt auch die set -oLösung, die ich vorgeschlagen habe. Es sollte auch für Optionen funktionieren, denen kein Flag zugeordnet ist, wie z -x.
vinc17