Bash-Set + x, ohne dass es gedruckt wird

91

Weiß jemand, ob wir set +xin Bash sagen können, ohne dass es gedruckt wird:

set -x
command
set +x

Spuren

+ command
+ set +x

aber es sollte nur drucken

+ command

Bash ist Version 4.1.10 (4). Das nervt mich schon seit einiger Zeit - die Ausgabe ist voll mit nutzlosen set +xZeilen, was die Trace-Funktion nicht so nützlich macht, wie sie sein könnte.

Andreas Spindler
quelle
Dies beantwortet Ihre Frage nicht, aber wenn Sie Ihr Skript ausführen, warum nicht:script.sh 2>&1 | grep -v 'set +x'
Cdarke

Antworten:

142

Ich hatte das gleiche Problem und konnte eine Lösung finden, die keine Unterschale verwendet:

set -x
command
{ set +x; } 2>/dev/null
McJoey
quelle
10
Tolle Antwort, nur eine Anmerkung: Ohne ein Semikolon nach dem Befehl funktioniert das nicht. und mit einem Semikolon, jedoch ohne Leerzeichen in geschweiften Klammern, wird ein Syntaxfehler ausgelöst.
Sdaau
9
Dies setzt den Exit-Status auf Null.
Garth Kidd
8
@GarthKidd Der Exit-Status wird bei jedem erfolgreichen Befehl auf Null gesetzt. set +xist so ein erfolgreicher Befehl
Daniel Alder
3
In Fällen, in denen Sie den Exit-Status von benötigen command, ist diese Variante eine Lösung : { STATUS=$?; set +x; } 2>/dev/null. Dann überprüfen Sie $STATUSin nachfolgenden Zeilen nach Belieben.
Greg Price
5
Separat ist hier eine Version, die etwas weiter golfen ist : { set +x; } 2>&-. Damit wird fd 2 sofort geschlossen, anstatt auf / dev / null zu zeigen. Einige Programme funktionieren nicht so gut, wenn sie versuchen, auf stderr zu drucken, weshalb / dev / null im Allgemeinen ein guter Stil ist. Aber die set -xVerfolgung der Shell handhabt es ganz gut, so dass es hier perfekt funktioniert, und es macht diese Beschwörung ein bisschen kürzer.
Greg Price
43

Sie können eine Unterschale verwenden. Beim Verlassen der Unterschale geht die Einstellung auf xverloren:

( set -x ; command )
Choroba
quelle
Nun, danke ... guter Punkt. Eigentlich ist mir "der Sub-Shell-Trick" bekannt. Ich hoffte, es könnte einfacher sein. Der Code wird erheblich geändert, wodurch der Code komplexer und weniger lesbar wird. IMHO wäre das schlimmer als mit dem Set + x Linien zu leben ...
Andreas Spindler
Ich sehe nicht, wie ( set -x \n command \n )schlimmer ist als set -x \n command \n set +x.
Chepner
3
@chepner: Sie können keine Variablen setzen.
Choroba
2
... und Sie können nicht cd: Es ändert nicht das aktuelle Verzeichnis in der übergeordneten Shell.
Andreas Spindler
Entschuldigung, ich bin mir nicht sicher, was ich für Ihren tatsächlichen Einwand gehalten habe. Es war eine lange Woche ...
Chepner
8

Ich habe erst kürzlich eine Lösung dafür gefunden, als ich mich darüber geärgert habe:

shopt -s expand_aliases
_xtrace() {
    case $1 in
        on) set -x ;;
        off) set +x ;;
    esac
}
alias xtrace='{ _xtrace $(cat); } 2>/dev/null <<<'

Auf diese Weise können Sie xtrace wie im Folgenden aktivieren und deaktivieren, wobei ich protokolliere, wie die Argumente Variablen zugewiesen werden:

xtrace on
ARG1=$1
ARG2=$2
xtrace off

Und Sie erhalten eine Ausgabe, die wie folgt aussieht:

$ ./script.sh one two
+ ARG1=one
+ ARG2=two
user108471
quelle
Cleverer Trick (obwohl Sie das /dev/stdinTeil nicht brauchen ). Die Einschränkung besteht darin, dass das Aktivieren der Alias-Erweiterung in Skripten unerwünschte Nebenwirkungen haben kann.
mklement0
Du hast recht. Ich habe die Antwort bearbeitet, um das Überflüssige zu entfernen /dev/stdin. Mir sind keine spezifischen Nebenwirkungen bekannt, da die nicht interaktive Umgebung keine Dateien laden sollte, die Aliase definieren. Welche Nebenwirkungen könnten auftreten?
user108471
1
Das ist ein guter Punkt - ich habe vergessen, dass Aliase nicht vererbt werden, daher ist das Risiko viel geringer als ich dachte (hypothetisch könnte Ihr Skript Code von Drittanbietern beziehen, der zufällig Aliase definiert, aber ich stimme zu, dass dies wahrscheinlich keine echte ist. Weltanliegen). +1
mklement0
1
@AndreasSpindler Könnten Sie näher erläutern, warum diese Technik Ihrer Meinung nach mit größerer Wahrscheinlichkeit vertraulichere Informationen verliert?
user108471
1
... im Grunde genommen, weil Aliase und Funktionen Konstrukte auf hoher Ebene sind. set +xEs ist viel schwieriger (wenn nicht unmöglich), Kompromisse einzugehen. Aber es ist immer noch eine gute und klare Lösung - wahrscheinlich die bisher beste.
Andreas Spindler
7

Wie wäre es mit einer Lösung, die auf einer vereinfachten Version von @ user108471 basiert:

shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ set +x; } 2>/dev/null'

trace_on
...stuff...
trace_off
Oliver
quelle
Wie wäre es damit? function () { set_plus_x='{ set +x; } 2>/dev/null' }
LexH
1

Dies ist eine Kombination einiger Ideen, die einen Codeblock einschließen und den Exit-Status beibehalten können.

#!/bin/bash
shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ PREV_STATUS=$? ; set +x; } 2>/dev/null; (exit $PREV_STATUS)'

trace_on
echo hello
trace_off
echo "status: $?"

trace_on
(exit 56)
trace_off

Bei Ausführung:

$ ./test.sh 
+ echo hello
hello
status: 0
+ exit 56
status: 56
user3286792
quelle