Bash seti + x yazdırılmadan


97

Bash'ta set +xbash olmadan söyleyip söyleyemeyeceğimizi bilen var mı :

set -x
command
set +x

izler

+ command
+ set +x

ama sadece yazdırmalı

+ command

Bash Sürüm 4.1.10'dur (4). Bu beni bir süredir rahatsız ediyor - çıktı işe yaramaz set +xçizgilerle darmadağın oluyor ve izleme tesisini olabildiğince kullanışlı hale getiriyor.


Bu, sorunuzu yanıtlamaz, ancak komut dosyanızı çalıştırdığınızda neden olmasın:script.sh 2>&1 | grep -v 'set +x'
cdarke

Yanıtlar:


149

Aynı problemi yaşadım ve alt kabuk kullanmayan bir çözüm bulabildim:

set -x
command
{ set +x; } 2>/dev/null

11
Harika cevap, sadece bir not: komuttan sonra noktalı virgül olmazsa bu işe yaramaz; ve bir noktalı virgülle, ancak küme parantezlerinde boşluklar olmadan, bir sözdizimi hatası ortaya çıkar.
sdaau

9
Bu çıkış durumunu sıfırlar.
Garth Kidd

8
@GarthKidd Çıkış durumu her başarılı komutla sıfırlanır. set +xçok başarılı bir komut
Daniel Alder

4
Eğer çıkış durumunu ihtiyaç durumlarda command, bu varyasyon bir çözümdür: { STATUS=$?; set +x; } 2>/dev/null. Sonra $STATUSboş zamanlarınızda sonraki satırlarda inceleyin .
Greg Price

6
Ayrı ayrı, burada biraz daha ileri golfed bir sürümü: { set +x; } 2>&-. Bu, fd 2'yi / dev / null konumuna getirmek yerine tamamen kapatır. Bazı programlar stderr'e yazdırmaya çalıştıklarında bunu iyi idare edemezler, bu yüzden / dev / null genel olarak iyi bir stildir; ama kabuğun set -xizleme sistemi gayet iyi idare ediyor, bu yüzden burada mükemmel çalışıyor ve bu büyülü sözü biraz kısaltıyor.
Greg Price

43

Bir alt kabuk kullanabilirsiniz. Alt kabuktan çıkıldığında, ayar xkaybolacak:

( set -x ; command )

Pekala, teşekkürler ... iyi nokta. Aslında "alt kabuk numarasının" farkındayım. Bundan daha kolay olacağını umuyordum. Kodda önemli değişiklikler içerir, kodu daha karmaşık ve daha az okunabilir hale getirir. IMHO set + x çizgileriyle yaşamaktan daha kötü olurdu ...
Andreas Spindler

Bundan ( set -x \n command \n )daha kötü nasıl olduğunu anlamıyorum set -x \n command \n set +x.
chepner

3
@chepner: Değişkenleri ayarlayamazsınız.
choroba

2
... ve yapamazsınız cd: üst kabuktaki mevcut dizini değiştirmez.
Andreas Spindler

Üzgünüm, asıl itirazınızın ne olduğunu düşündüğümden emin değilim. Uzun bir hafta oldu ...
chepner

8

Kısa bir süre önce buna sinirlendiğimde buna bir çözüm buldum:

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

Bu, xtrace'i aşağıdaki gibi etkinleştirmenize ve devre dışı bırakmanıza olanak tanır; burada, değişkenlerin değişkenlere nasıl atandığını günlüğe kaydediyorum:

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

Ve şöyle görünen çıktılar elde edersiniz:

$ ./script.sh one two
+ ARG1=one
+ ARG2=two

Akıllı numara ( /dev/stdinparçaya ihtiyacınız olmasa da ). Uyarı, komut dosyalarında takma ad genişletmeyi açmanın istenmeyen yan etkilere sahip olabileceğidir.
mklement0

Haklısın. Gereksiz olanı kaldırmak için cevabı düzenledim /dev/stdin. Etkileşimli olmayan ortamın takma adları tanımlayan hiçbir dosyayı yüklememesi gerektiğinden, herhangi bir özel yan etkinin farkında değilim. Ne tür yan etkiler olabilir?
user108471

1
Bu iyi bir nokta - Takma adların kalıtımla alınmadığını unuttum, bu yüzden risk düşündüğümden çok daha küçük (varsayımsal olarak, senaryonuz, takma adları tanımlayan üçüncü taraf kodlarından kaynaklanıyor olabilir, ancak bunun muhtemelen gerçek olmadığını kabul ediyorum. dünya endişesi). +1
mklement0

1
@AndreasSpindler Bu tekniğin neden daha hassas bilgileri sızdırmasının daha olası olduğunu düşündüğünüzü açıklayabilir misiniz?
user108471

1
... temelde takma adlar ve işlevler üst düzey yapılar olduğu için. set +xuzlaşmak (imkansız değilse) çok daha zordur. Ama yine de iyi ve doğru bir çözüm - muhtemelen şimdiye kadarki en iyisi.
Andreas Spindler

7

@ User108471'in basitleştirilmiş bir sürümüne dayalı bir çözüme ne dersiniz:

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

trace_on
...stuff...
trace_off

Buna ne dersin? function () { set_plus_x='{ set +x; } 2>/dev/null' }
LexH

1

Bu, bir kod bloğunu çevreleyen ve çıkış durumunu koruyan birkaç fikrin birleşimidir.

#!/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
echo "status: $?"

Yürütüldüğünde:

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

Güzel çaba ama sanırım ()etrafında exitgerekli değildir. Tamam. En paranoyak, ancak bu kod genel olarak kullanılırsa iyi bir saldırı vektörü sahip Belki o: yeniden tanımlamak trace_onve trace_offidam komutları okur iğne kodu. Bu tür "araçları" tek başına kullanırsanız, bu öğretici olur, ancak kod başkalarıyla birlikte kullanılırsa, bu tür standartlaştırılmamış işlevlerin faydalarının dezavantajlarından ağır basıp basmadığını dikkate almanız gerekir. Şahsen ben { set +x; } 2>/dev/nullbu yapı yaygın olarak anlaşıldığı ve çıkış durumunu değiştirmediği için yerleştim.
Andreas Spindler

Teşekkürler. Bu yaklaşımı meslektaşlarımla paylaştım ve hem çıktıyı hem de kodu daha az gürültülü tutmasını seviyorlar. ()Çevresine gelince exit 56; bu basitçe, alt işlemin çıkış durumunun bash betiğinde erişilebilir olduğunu gösterebilmem için yapıldı; parantezler olmadan, bir alt işlem haline gelmezdi ve komut dosyası o noktada status = 65 ile çıkardı.
user3286792
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.