Jak mogę sprawdzić, czy aktualnie wykonywany skrypt bash został wywołany z opcją -x w celu debugowania?

11

Mam skrypt, launch.shktóry wykonuje się jako inny użytkownik, aby tworzyć pliki z poprawnym właścicielem. Chcę przekazać -x do tego wywołania, jeśli zostało ono pierwotnie przekazane do skryptu

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

Przeczytałem stronę debugowania bash, ale wydaje się, że nie ma wyraźnej opcji, która mówi, czy oryginalny skrypt został uruchomiony -x.

Dan Dascalescu
źródło

Odpowiedzi:

15

Wiele flag, które można przekazać bashw wierszu poleceń, to setflagi. setjest wbudowaną powłoką, która może przełączać te flagi w czasie wykonywania. Na przykład wywoływanie skryptu bash -x foo.shjest w zasadzie takie samo, jak wykonywanie set -xna górze skryptu.

Wiedząc, że setjest to wbudowana powłoka odpowiedzialna za to, pozwala nam wiedzieć, gdzie szukać. Teraz możemy to zrobić help seti otrzymujemy:

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

Z tego wynika, że $-powinno to powiedzieć nam, które flagi są włączone.

$ bash -c 'echo $-'
hBc

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

Zasadniczo musisz po prostu zrobić:

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

Jako bonus, jeśli chcesz skopiować wszystkie flagi, możesz to zrobić

bash -$- /other/script.sh
Patrick
źródło
1
Musisz użyć [[ $- == *x* ]]do dopasowania wzorca.
glenn jackman
1
Lub możesz użyć standardu case $- in *x*) ... ;; *) ... ;; esac. Przydatne jest poznanie tego zastosowania caseskryptów, które mają być przenośne, a teraz, gdy o tym wiem, łatwiej mi to zapamiętać, niż zapamiętać „jeśli jest to specyficzne dla basha, to [[inaczej case”.
hvd
OK, cała seria komentarzy mogłaby zostać usunięta.
l0b0
$-wyjścia hB. Co oznaczają -hi -Bflagi / argumenty zrobić? Nie widzę tego na stronie podręcznika użytkownika bash .
Dan Dascalescu
3

set -owyświetli, xtrace onjeśli -xzostanie użyty, w przeciwnym razie xtrace off.

vinc17
źródło
2

Chociaż odpowiedź @Patrick jest „właściwa”, możesz również przekazać parametr lub wyeksportowaną zmienną do skryptu podrzędnego, który mówi jej, co ma robić - na przykład włączyć śledzenie.

Ma to tę wadę, że (uważam) musisz ponownie wyeksportować go na każdy poziom skryptu, który zamierzasz wprowadzić.

Ma tę zaletę, że może selektywnie śledzić (lub w inny sposób wpływać) tylko skrypt (y), z których potrzebujesz dane wyjściowe / zmodyfikowane zachowanie - aby ograniczyć zbędne dane wyjściowe itp. Np. Śledzenie może być wyłączone dla skryptu wywołującego i nadal będzie włączony w wywoływanym skrypcie. To nie jest propozycja wszystkiego albo nic.

Nie jest częścią twojego pytania, ale dotyczy:

Czasami definiuję zmienną taką jak

E=""
E="echo "

lub

E=""
E=": "

i użyj go (w wielu instrukcjach) jak

"${E}" rsync ...

lub tylko dla drugiej odmiany

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

Następnie po prostu komentuję drugą definicję, kiedy chcę, aby polecenia były uruchamiane. Możesz również użyć tej techniki zamiast parametru lub wyeksportowanej zmiennej.

W obu przypadkach należy uważać na instrukcje złożone, ponieważ gwarantuje się, że metoda będzie działać tylko na pierwszej instrukcji na liście złożonej.

Joe
źródło
1

Możesz pobrać PID procesu, a następnie zbadać tabelę procesów za pomocą ps, aby zobaczyć, jakie były argumenty.

Paul Calabro
źródło
Możesz pobrać proces PID poprzez: $$
Paul Calabro
2
Nie sądzę, aby był to dobry pomysł, ponieważ jeśli -xzostał ustawiony w skrypcie, nie zostanie wyświetlony w pswyniku. To rozwiązanie i tak jest nieefektywne.
vinc17
To uczciwy argument. Właściwie to nie wiedziałem o zmiennej $. Wydaje się, że to znacznie lepsze podejście do rozwiązania tego problemu.
Paul Calabro
1
Jest też set -orozwiązanie, które zaproponowałem. Powinien także działać w przypadku opcji, które nie mają powiązanej flagi -x.
vinc17