Ben istiyorum set -x
körlemesine ayar sonradan bunun yerine (ben ayarladıktan önceki haline geri dönmek) Senaryomun başında ve "geri alma" da +x
. Mümkün mü?
Not: Zaten burada kontrol ettim ; Bu, söyleyebileceğim kadarıyla sorumu cevaplamadı.
Ben istiyorum set -x
körlemesine ayar sonradan bunun yerine (ben ayarladıktan önceki haline geri dönmek) Senaryomun başında ve "geri alma" da +x
. Mümkün mü?
Not: Zaten burada kontrol ettim ; Bu, söyleyebileceğim kadarıyla sorumu cevaplamadı.
Yanıtlar:
set -x
Sadece bir tersine çevirmek için a set +x
. Bir dizgenin tersi çoğu zaman set -str
a +
: ile aynı dizgedir set +str
.
Genel olarak, hepsini geri yüklemek için (bash hakkında aşağıda okuyun errexit
) kabuk seçeneklerini ( set
komutla değiştirildi ) yapabilecekleriniz (bash shopt
seçenekleri hakkında aşağıda da okuyun ):
oldstate="$(set +o); set -$-" # POSIXly store all set options.
.
.
set -vx; eval "$oldstate" # restore all options stored.
Bu komut:
shopt -po xtrace
seçeneğin durumunu yansıtan yürütülebilir bir dize oluşturur. p
Bayrak araçları yazdırmak ve o
biz tarafından seçeneği (s) kümesi hakkında soruyorsun bayrak belirtir set
(tarafından seçeneği (ler) kümesine karşı komuta shopt
komuta). Bu dizeyi bir değişkene atayabilir ve ilk durumu geri yüklemek için değişkeni komut dosyanızın sonunda yürütebilirsiniz.
# store state of xtrace option.
tracestate="$(shopt -po xtrace)"
# change xtrace as needed
echo "some commands with xtrace as externally selected"
set -x
echo "some commands with xtrace set"
# restore the value of xtrace to its original value.
eval "$tracestate"
Bu çözüm aynı anda birden fazla seçenek için çalışıyor:
oldstate="$(shopt -po xtrace noglob errexit)"
# change options as needed
set -x
set +x
set -f
set -e
set -x
# restore to recorded state:
set +vx; eval "$oldstate"
Ekleme set +vx
, uzun bir seçenekler listesinin yazdırılmasını engeller.
Ve, seçenek adlarını listelemezseniz,
oldstate="$(shopt -po)"
size tüm seçeneklerin değerlerini verir. o
Bayraktan dışarı çıkarsanız, aynı şeyleri shopt
seçeneklerle de yapabilirsiniz:
# store state of dotglob option.
dglobstate="$(shopt -p dotglob)"
# store state of all options.
oldstate="$(shopt -p)"
Bir set
seçeneğin ayarlanıp ayarlanmadığını test etmeniz gerekirse, bunu yapmanın en salak (Bash) yolu şudur:
[[ -o xtrace ]]
diğer iki benzer testten daha iyidir:
[[ $- =~ x ]]
[[ $- == *x* ]]
Testlerden herhangi biriyle bu işe yarar:
# record the state of the xtrace option in ts (tracestate):
[ -o xtrace ] && ts='set -x' || ts='set +x'
# change xtrace as needed
echo "some commands with xtrace as externally selected"
set -x
echo "some commands with xtrace set"
# set the xtrace option back to what it was.
eval "$ts"
Bir shopt
seçeneğin durumunu nasıl test edeceğiniz aşağıda açıklanmaktadır :
if shopt -q dotglob
then
# dotglob is set, so “echo .* *” would list the dot files twice.
echo *
else
# dotglob is not set. Warning: the below will list “.” and “..”.
echo .* *
fi
Tüm set
seçenekleri saklamak için POSIX uyumlu basit bir çözümdür :
set +o
olan POSIX standardında tarif edildiği gibidir:
+ o
Mevcut seçenek ayarlarını standart çıktıya, aynı seçenek ayarlarını elde eden komutlar gibi kabuğa yeniden giriş yapmak için uygun bir formatta yazın.
Yani, basitçe:
oldstate=$(set +o)
set
komutu kullanarak ayarlanan tüm seçeneklerin değerlerini koruyacaktır .
Yine, seçenekleri orijinal değerlerine geri yüklemek, değişkenin yürütülmesinden ibarettir:
set +vx; eval "$oldstate"
Bu, Bash'in kullanımına tam olarak eşdeğerdir shopt -po
. O edeceği Not değil kapsayacak tüm olası Bash bu bazıları tarafından oluşturulduğu takdirde seçenekleri shopt
.
shopt
Bash'da listelenen birçok başka kabuk seçeneği vardır :
$ shopt
autocd off
cdable_vars off
cdspell off
checkhash off
checkjobs off
checkwinsize on
cmdhist on
compat31 off
compat32 off
compat40 off
compat41 off
compat42 off
compat43 off
complete_fullquote on
direxpand off
dirspell off
dotglob off
execfail off
expand_aliases on
extdebug off
extglob off
extquote on
failglob off
force_fignore on
globasciiranges off
globstar on
gnu_errfmt off
histappend on
histreedit off
histverify on
hostcomplete on
huponexit off
inherit_errexit off
interactive_comments on
lastpipe on
lithist off
login_shell off
mailwarn off
no_empty_cmd_completion off
nocaseglob off
nocasematch off
nullglob off
progcomp on
promptvars on
restricted_shell off
shift_verbose off
sourcepath on
xpg_echo off
Bunlar yukarıda ayarlanan değişkene eklenebilir ve aynı şekilde geri yüklenebilir:
$ oldstate="$oldstate;$(shopt -p)"
.
. # change options as needed.
.
$ eval "$oldstate"
Bunu yapmak mümkündür ( korunmasını $-
sağlamak errexit
için eklenmiştir ):
oldstate="$(shopt -po; shopt -p); set -$-"
set +vx; eval "$oldstate" # use to restore all options.
Not : Her kabuğun ayarlanmış veya ayarlanmamış seçeneklerin listesini oluşturmak için biraz farklı bir yolu vardır (tanımlanmış farklı seçeneklerden bahsetmiyorum), bu nedenle dizeler kabuklar arasında taşınabilir değildir, ancak aynı kabuk için geçerlidir.
zsh
ayrıca 5.3 sürümünden bu yana (POSIX’ten sonra) doğru şekilde çalışır Önceki sürümlerde sadece kısmen ile POSIX izledi set +o
o komutları gibi kabuğuna reinput için uygun bir formatta seçenekleri basılmış ki, ama sadece set seçenekleri (Bu baskı yoktu un-set seçenekleri).
Mksh (ve sonuç olarak lksh) henüz bunu yapamamıştır (MIRBSD KSH R54 2016/11/11). Mksh kılavuzu bunu içerir:
Gelecekteki bir sürümde, + o ayarının geçerli seçenekleri geri yüklemek için POSIX uyumlu davranması ve komutları yazdırması gerekir.
Bash'te, set -e
( errexit
) değeri alt kabuklarda sıfırlanır, bu da değerini set +o
$ (…) alt kabuğunda yakalamayı zorlaştırır .
Çözüm olarak, şunları kullanın:
oldstate="$(set +o); set -$-"
Almquist kabuğu ve türevleri ( dash
, sh
en azından NetBSD / FreeBSD ) ve bash
4.4 veya üstü ile, bir işlev için yerel olarak seçenekler yapabilirsiniz local -
(isterseniz $-
değişkeni yerel yap):
$ bash-4.4 -c 'f() { local -; set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace
Bu kaynaklı dosyalar için geçerli değildir , ancak source
bunun source() { . "$@"; }
üzerinde çalışacak şekilde yeniden tanımlayabilirsiniz .
İle ksh88
, seçenek değişiklikleri varsayılan olarak işlev için yereldir. Bu ksh93
, sadece function f { ...; }
sözdizimi ile tanımlanan işlevler için geçerlidir (ve kapsam, ksh88 dahil diğer kabuklarda kullanılan dinamik kapsamayla karşılaştırıldığında statiktir):
$ ksh93 -c 'function f { set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace
In zsh
, bu localoptions
seçeneği ile bitti :
$ zsh -c 'f() { set -o localoptions; set -x; echo test; }; f; echo no trace'
+f:0> echo test
test
no trace
POSIXly şunları yapabilirsiniz:
case $- in
(*x*) restore=;;
(*) restore='set +x'; set -x
esac
echo test
{ eval "$restore";} 2> /dev/null
echo no trace
Bununla birlikte, bazı kabuklar + 2> /dev/null
geri yükleme işleminde bir çıktı verecektir (ve zaten etkinleştirildiyse bu yapının izini görürsünüz ). Bu yaklaşım aynı zamanda yeniden giriş yapmaz (bunu, kendisini ya da aynı numarayı kullanan başka bir işlevi çağıran bir işlevde yaparsanız).case
set -x
Etrafında çalışan bir yığının nasıl uygulanacağına ilişkin https://github.com/stephane-chazelas/misc-scripts/blob/master/locvar.sh (POSIX kabukları için değişkenler ve seçenekler için yerel kapsam) bölümüne bakın .
Herhangi bir kabukla, seçeneklerin kapsamını sınırlamak için alt kabuklar kullanabilirsiniz
$ sh -c 'f() (set -x; echo test); f; echo no trace'
+ echo test
test
no trace
Ancak bu, sadece seçeneklerin değil, her şeyin kapsamını da sınırlar (değişkenler, işlevler, takma adlar, yönlendirmeler, geçerli çalışma dizini ...).
oldstate=$(set +o)
tüm seçenekleri saklamanın daha basit (ve POSIX) bir yolu.
pdksh
/ mksh
(ve diğer pdksh türevleri) gibi kabuk uygulamaları için çalışmayan ya zsh
da set +o
yalnızca varsayılan ayarlardan sapmaları çıktıran iyi bir nokta . Bu bash / dash / yash için işe yarar ancak taşınabilir değildir.
Ayarlanmış $-
olup olmadığını görmek için değişkeni başında okuyabilir -x
ve ardından bir değişkene kaydedebilirsiniz.
if [[ $- == *x* ]]; then
was_x_set=1
else
was_x_set=0
fi
Gönderen Bash kılavuzda :
($ -, bir tire.) Çağrıldığında, set yerleşik komutu ile veya kabuğun kendisi tarafından (-i seçeneği gibi) ayarlanan geçerli seçenek bayraklarına genişletir.
[[ $SHELLOPTS =~ xtrace ]] && wasset=1
set -x
echo rest of your script
[[ $wasset -eq 0 ]] && set +x
Kısaca, $ SHELLOPTS açık olan bayraklarla ayarlanır. Xtrace'i açmadan önce kontrol edin ve yalnızca önceden kapalıysa xtrace'ı sıfırlayın.
Açıkça belirtmek gerekirse set -x
, betiğin süresi boyunca geçerli olacaksa ve bu sadece geçici bir test önlemidir (çıktının kalıcı bir parçası olmamalıdır), ya da betiği w / -x
seçeneği ile çağırın;
$ bash -x path_to_script.sh
... veya, -x
seçeneği ekleyerek hata ayıklama çıktısını etkinleştirmek için betiği (ilk satır) geçici olarak değiştirin :
#!/bin/bash -x
...rest of script...
Bunun muhtemelen istedikleriniz için çok geniş bir vuruş olduğunu fark ettim, ancak senaryoyu (benim deneyimlerime göre) muhtemelen kaldırmak isteyeceğiniz geçici şeylerle aşırı karmaşık hale getirmeden, etkinleştirmenin / devre dışı bırakmanın en basit ve en hızlı yolu.
Bu, POSIX $-
özel parametresiyle görünen bayrakları kaydetme ve geri yükleme işlevlerini sağlar . local
Yerel değişkenler için uzantı kullanıyoruz . POSIX uyumlu bir taşınabilir komut dosyasında, genel değişkenler kullanılır ( local
anahtar kelime yok ):
save_opts()
{
echo $-
}
restore_opts()
{
local saved=$1
local on
local off=$-
while [ ${#saved} -gt 0 ] ; do
local rest=${saved#?}
local first=${saved%$rest}
if echo $off | grep -q $first ; then
off=$(echo $off | tr -d $first)
fi
on="$on$first"
saved=$rest
done
set ${on+"-$on"} ${off+"+$off"}
}
Bu, kesme bayraklarının Linux çekirdeğinde nasıl kaydedildiğine ve geri yüklendiğine benzer şekilde kullanılır:
Shell: Kernel:
flags=$(save_opts) long flags;
save_flags (flags);
set -x # or any other local_irq_disable(); /* disable irqs on this core */
# ... -x enabled ... /* ... interrupts disabled ... */
restore_opts $flags restore_flags(flags);
# ... x restored ... /* ... interrupts restored ... */
Bu, $-
değişkende ele alınmayan genişletilmiş seçeneklerin hiçbirinde işe yaramaz .
Sadece POSIX'in aradığım şeye sahip olduğunu fark ettim: +o
argümanı set
bir seçenek değil, eğer varsa eval
, seçenekleri geri yükleyecek bir sürü komuttan oluşan bir komut . Yani:
flags=$(set +o)
set -x
# ...
eval "$flags"
Bu kadar.
Küçük bir sorun, eğer -x
seçenek bundan önce döndürülürse eval
, çirkin bir set -o
komut dalgası görülür. Bunu ortadan kaldırmak için aşağıdakileri yapabiliriz:
set +x # turn off trace not to see the flurry of set -o.
eval "$flags" # restore flags
Bir alt kabuk kullanabilirsiniz.
(
set …
do stuff
)
Other stuff, that set does not apply to