`Set -x` এর মতো শেল বিকল্পগুলির মানটি পুনরুদ্ধার করবেন কীভাবে?


47

আমি চাই set -xঅন্ধ সেটিং আমার স্ক্রিপ্ট শুরুতে এবং "পূর্বাবস্থা" এটা (অঙ্গরাজ্য ফিরে যেতে আগে আমি এটি সেট) এ পরে পরিবর্তে +x। এটা কি সম্ভব?

PS: আমি ইতিমধ্যে এখানে চেক করেছি ; আমি যতটা বলতে পারি তা আমার প্রশ্নের উত্তর বলে মনে হচ্ছে না।

উত্তর:


58

বিমূর্ত

একটি set -xঠিক চালানো একটি বিপরীত set +x। বেশিরভাগ সময়ে, একটি স্ট্রিং এর বিপরীত set -strএকটি সঙ্গে একই স্ট্রিং +: set +str

সাধারণভাবে, সমস্ত (পুনরুদ্ধারের নীচে পড়ুন errexit) শেল বিকল্পগুলি ( setকমান্ডের সাহায্যে পরিবর্তিত) পুনরুদ্ধার করতে আপনি করতে পারেন (নীচে বাশ shoptবিকল্পগুলি সম্পর্কেও পড়ুন ):

oldstate="$(set +o); set -$-"                # POSIXly store all set options.
.
.
set -vx; eval "$oldstate"         # restore all options stored.

দীর্ঘ বিবরণ

সজোরে আঘাত

এই আদেশ:

shopt -po xtrace

একটি এক্সিকিউটেবল স্ট্রিং তৈরি করবে যা বিকল্পের অবস্থা প্রতিফলিত করে। pপতাকা মানে, মুদ্রণ এবং oপতাকা নির্দিষ্ট করে আমরা যে বিষয়ে বিকল্প (গুলি) সেট জিজ্ঞাসা করা হয় setকমান্ড (যেমন দ্বারা বিকল্প (গুলি) সেট বিরোধিতা shoptকমান্ড)। আপনি এই স্ট্রিংটিকে একটি ভেরিয়েবলের জন্য বরাদ্দ করতে পারেন এবং প্রাথমিক অবস্থার পুনরুদ্ধার করতে আপনার স্ক্রিপ্টের শেষে ভেরিয়েবলটি কার্যকর করতে পারেন।

# 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"

এই সমাধান একসাথে একাধিক বিকল্পের জন্য কাজ করে:

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"

যোগ করা set +vxবিকল্পগুলির দীর্ঘ তালিকার মুদ্রণ এড়ানো।


এবং, যদি আপনি কোনও বিকল্পের নাম তালিকাভুক্ত না করেন,

oldstate="$(shopt -po)"

এটি আপনাকে সমস্ত বিকল্পের মান দেয়। এবং, যদি আপনি oপতাকাটি ছেড়ে দেন তবে আপনি বিকল্পগুলি সহ একই জিনিস করতে পারেন shopt:

# store state of dotglob option.
dglobstate="$(shopt -p dotglob)"

# store state of all options.
oldstate="$(shopt -p)"

যদি আপনার কোনও setবিকল্প সেট করা আছে কিনা তা পরীক্ষা করে দেখার দরকার হয় তবে এটি করার জন্য সর্বাধিক প্রতিমা (বাশ) উপায়:

[[ -o xtrace ]]

যা অন্য দুটি অনুরূপ পরীক্ষার চেয়ে ভাল:

  1. [[ $- =~ x ]]
  2. [[ $- == *x* ]]

যে কোনও পরীক্ষার সাথে, এটি কাজ করে:

# 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"

কোনও shoptবিকল্পের অবস্থা কীভাবে পরীক্ষা করা যায় তা এখানে :

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

POSIX

সমস্ত setঅপশন সংরক্ষণ করার জন্য একটি সহজ, পসিএক্স-সম্মতিজনক সমাধান :

set +o

যা POSIX মান হিসাবে বর্ণনা করা হয়েছে :

+ O

    একই অপশন সেটিংস অর্জনকারী কমান্ড হিসাবে শেলটিতে পুনরায় সংযোগের জন্য উপযুক্ত এমন ফর্ম্যাটে স্ট্যান্ডার্ড আউটপুটে বর্তমান বিকল্প সেটিংস লিখুন।

সুতরাং, সহজভাবে:

oldstate=$(set +o)

setকমান্ডটি ব্যবহার করে সেট করা সমস্ত বিকল্পের মানগুলি সংরক্ষণ করবে ।

আবার বিকল্পগুলি তাদের মূল মানগুলিতে পুনরুদ্ধার করা ভেরিয়েবলটি কার্যকর করার বিষয়:

set +vx; eval "$oldstate"

এটি ব্যাশের ব্যবহারের সমান সমান shopt -po। মনে রাখবেন যে এটি সমস্ত সম্ভাব্য বাশ বিকল্পগুলি কভার করবে না , যেমনগুলির কয়েকটি সেট করে রয়েছে ।shopt

বাশ স্পেশাল কেস

shoptব্যাশে তালিকাভুক্ত আরও অনেক শেল বিকল্প রয়েছে :

$ 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

এগুলি উপরের চলক সেটগুলিতে যুক্ত করা যেতে পারে এবং একইভাবে পুনরুদ্ধার করা যেতে পারে:

$ oldstate="$oldstate;$(shopt -p)"
.
.                                   # change options as needed.
.
$ eval "$oldstate" 

এটি করা সম্ভব (এটি সংরক্ষণের $-জন্য নিশ্চিত errexitকরা হয়েছে):

oldstate="$(shopt -po; shopt -p); set -$-"

set +vx; eval "$oldstate"             # use to restore all options.

নোট : সেট বা আনসেট করা বিকল্পগুলির তালিকা তৈরির জন্য প্রতিটি শেলের কিছুটা আলাদা উপায় রয়েছে (সংজ্ঞায়িত বিভিন্ন বিকল্পের উল্লেখ না করা), সুতরাং শেলগুলির মধ্যে স্ট্রিংগুলি পোর্টেবল নয়, তবে একই শেলের জন্য বৈধ।

zsh বিশেষ ক্ষেত্রে

zshসংস্করণ 5.3 থেকে সঠিকভাবে (পসিক্স অনুসরণ করে) কাজ করে। পূর্ববর্তী সংস্করণগুলিতে এটি পোজিক্সকে কেবলমাত্র আংশিকভাবে অনুসরণ set +oকরেছিল যেটি কমান্ড হিসাবে শেলটিতে পুনরায় লাগানোর জন্য উপযুক্ত এমন ফর্ম্যাটে বিকল্পগুলি ছাপিয়েছিল, তবে কেবল সেট বিকল্পগুলির জন্য (এটি আন-সেট বিকল্পগুলি প্রিন্ট করে না )।

mksh বিশেষ মামলা

Mksh (এবং ফলস্বরূপ lksh) এখনও এটি করতে সক্ষম হয়নি (MIRBSD KSH R54 2016/11/11) এটি করতে সক্ষম। ম্যাক্স ম্যানুয়ালটিতে এটি রয়েছে:

ভবিষ্যতের সংস্করণে, সেট + o পরিবর্তে বর্তমান বিকল্পগুলি পুনরুদ্ধার করতে পসিক্স অনুগত এবং মুদ্রণ কমান্ডগুলি আচরণ করবে।

সেট - বিশেষ মামলা

ব্যাশে, set -e( errexit) এর মান উপ-শেলগুলির মধ্যে পুনরায় সেট করা হয়, যার ফলে এটির মানটি set +oএকটি-(…) সাব-শেলের ভিতরে দিয়ে ক্যাপচার করা কঠিন করে তোলে ।

কার্যকারণ হিসাবে, ব্যবহার করুন:

oldstate="$(set +o); set -$-"

21

অ্যালকুইস্ট শেল এবং ডেরিভেটিভস ( dash, নেটবিএসডি / ফ্রিবিএসডি shকমপক্ষে) এবং bash৪.৪ বা তার বেশি দিয়ে আপনি কোনও ফাংশনটিতে বিকল্পগুলি স্থানীয় করতে পারেন local -( $-যদি আপনি চান তবে ভেরিয়েবল স্থানীয় করুন):

$ bash-4.4 -c 'f() { local -; set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace

যে প্রযোজ্য নয় sourced ফাইল, কিন্তু আপনি পুনরায় সংজ্ঞায়িত করতে sourceযেমন source() { . "$@"; }প্রায় কাজ।

সাথে ksh88, বিকল্প পরিবর্তনগুলি ডিফল্টরূপে ফাংশনে স্থানীয় হয়। এর সাথে সিনট্যাক্সের ksh93সাথে সংজ্ঞায়িত ফাংশনগুলির ক্ষেত্রে এটিই কেবলমাত্র function f { ...; }(এবং কেএস 88 সহ অন্যান্য শেলগুলিতে ব্যবহৃত ডায়নামিক স্কোপিংয়ের তুলনায় স্কোপিং স্থির):

$ ksh93 -c 'function f { set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace

ইন zsh, এটি localoptionsবিকল্প দ্বারা সম্পন্ন হয়েছে :

$ zsh -c 'f() { set -o localoptions; set -x; echo test; }; f; echo no trace'
+f:0> echo test
test
no trace

প্যাসিকলি, আপনি এটি করতে পারেন:

case $- in
  (*x*) restore=;;
  (*) restore='set +x'; set -x
esac
echo test
{ eval "$restore";} 2> /dev/null
echo no trace

তবে কিছু শাঁস + 2> /dev/nullপুনরুদ্ধার উপর একটি আউটপুট হবে (এবং আপনি ইতিমধ্যে সক্ষম ছিল যদি অবশ্যই এই নির্মাণের ট্রেস দেখতে পাবেন )। এই পদ্ধতির পুনরায় প্রবেশকারীও নয় (যেমন আপনি যদি এমন কোনও ফাংশনে এটি করেন যা নিজেকে কল করে বা একই কৌশল ব্যবহার করে এমন কোনও ফাংশন)।caseset -x

তার চারপাশে কাজ করে এমন একটি স্ট্যাক কীভাবে কার্যকর করা যায় তার জন্য https://github.com/stephane-chazelas/misc-scriptts/blob/master/locvar.sh (POSIX শেলগুলির জন্য ভেরিয়েবল এবং স্থানীয় বিকল্পগুলির জন্য) দেখুন।

যে কোনও শেলের সাথে, আপনি বিকল্পগুলির পরিধি সীমাবদ্ধ করতে সাবশেলগুলি ব্যবহার করতে পারেন

$ sh -c 'f() (set -x; echo test); f; echo no trace'
+ echo test
test
no trace

যাইহোক, এটি কেবলমাত্র বিকল্পগুলি নয়, সমস্ত কিছুর (ভেরিয়েবল, ফাংশন, উপকরণ, পুনর্নির্দেশগুলি, বর্তমান ওয়ার্কিং ডিরেক্টরি ...) সীমিত করে।


বাশ 4.4 4 দিন আগে বেরিয়েছে (16-সেপ্টেম্বর
-2016

আমার কাছে মনে হচ্ছে এটি oldstate=$(set +o)সমস্ত বিকল্প সঞ্চয় করার একটি সহজ (এবং পসিক্স) উপায়।
sorontar

@ সোরন্টার, ভাল পয়েন্ট যদিও এটি শেল বাস্তবায়ন যেমন pdksh/ mksh(এবং অন্যান্য পিডিক্স ডেরিভেটিভস) এর জন্য কাজ করে না বা zshযেখানে set +oকেবলমাত্র ডিফল্ট সেটিংস থেকে বিচ্যুতিগুলি আউটপুট করে। এটি ব্যাশ / ড্যাশ / ইয়াশের জন্য কাজ করবে তবে পোর্টেবল হবে না।
স্টাফেন চেজেলাস

13

আপনি $-শুরুতে ভেরিয়েবলটি -xসেট করা আছে কিনা তা দেখতে শুরুতে পড়তে পারেন এবং তারপরে এটি একটি ভেরিয়েবলে সংরক্ষণ করতে পারেন যেমন, যেমন

if [[ $- == *x* ]]; then
  was_x_set=1
else
  was_x_set=0
fi

থেকে ব্যাশ ম্যানুয়াল :

($ -, একটি হাইফেন।) অনুরোধের সময়, সেট বিল্টিন কমান্ড দ্বারা বা শেল নিজেই সেট করে সেট করে (যেমন -i বিকল্প হিসাবে) বর্তমান বিকল্পগুলির পতাকাগুলিতে প্রসারিত করে।


7
[[ $SHELLOPTS =~ xtrace ]] && wasset=1
set -x
echo rest of your script
[[ $wasset -eq 0 ]] && set +x

ব্যাশে , are শেল্পপ্টসগুলি চালু করা পতাকাগুলির সাথে সেট করা থাকে। আপনি অক্সট্রেস চালু করার আগে এটি পরীক্ষা করে দেখুন এবং কেবলমাত্র অক্সট্র্যাসটি আগে বন্ধ থাকলে পুনরায় সেট করুন।


5

কেবল স্পষ্টভাবে বলতে গেলে, যদি set -xস্ক্রিপ্টের সময়কালের জন্য কার্যকর হতে হয় এবং এটি কেবলমাত্র একটি অস্থায়ী পরীক্ষার ব্যবস্থা (স্থায়ীভাবে আউটপুটটির অংশ না হওয়া) তবে স্ক্রিপ্ট ডাব্লু / -xবিকল্পটিকে অনুরোধ করুন, যেমন,

$ bash -x path_to_script.sh

... বা, -xঅপশনটি যুক্ত করে ডিবাগ আউটপুট সক্ষম করতে অস্থায়ীভাবে স্ক্রিপ্ট (প্রথম লাইন) পরিবর্তন করুন :

#!/bin/bash -x
...rest of script...

আমি বুঝতে পারি এটি আপনি যা চান তার জন্য এটি সম্ভবত খুব বিস্তৃত স্ট্রোক, তবে সাময়িক স্টাফের সাথে স্ক্রিপ্টটিকে অতিরিক্ত জটিলতায় না ফেলেই সম্ভবত সক্ষম / অক্ষম করার সহজতম এবং দ্রুততম উপায় যা আপনি সম্ভবত যেভাবেই মুছে ফেলতে চাইবেন (আমার অভিজ্ঞতায়)।


3

এটি পসিক্স $-বিশেষ প্যারামিটারের মাধ্যমে দৃশ্যমান পতাকাগুলি সংরক্ষণ এবং পুনরুদ্ধার করার জন্য ফাংশন সরবরাহ করে । আমরা localস্থানীয় ভেরিয়েবলের জন্য এক্সটেনশনটি ব্যবহার করি । কোনও পসিক্স মেনে চলতে পোর্টেবল স্ক্রিপ্টে, বৈশ্বিক ভেরিয়েবলগুলি ব্যবহৃত হত (কোনও localকীওয়ার্ড নেই):

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"}
}

এটি লিনাক্স কার্নেলের মধ্যে অন্তরায়যুক্ত পতাকাগুলি কীভাবে সংরক্ষণ এবং পুনরুদ্ধার করা হয় একইভাবে ব্যবহৃত হয়:

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 ... */

এটি $-ভেরিয়েবলের আওতায় নেই এমন কোনও বর্ধিত বিকল্পের জন্য কাজ করবে না ।

সবেমাত্র লক্ষ্য করা গেছে যে আমি যা খুঁজছিলাম তার মধ্যে পসিএক্স রয়েছে: +oআর্গুমেন্টটি setকোনও বিকল্প নয়, একটি কমান্ড যা একটি গুচ্ছ কমান্ডকে ডাম্প করে দেয়, যদি eval-ed বিকল্পগুলি পুনরুদ্ধার করবে। তাই:

flags=$(set +o)

set -x

# ...

eval "$flags"

এটাই.

একটি ছোট সমস্যা হ'ল -xবিকল্পটি যদি এর আগে পরিণত হয়, তবে কমান্ডগুলির evalএকটি কুৎসিত ঝগড়া set -oদেখা যায়। এটি দূর করতে আমরা নিম্নলিখিতগুলি করতে পারি:

set +x             # turn off trace not to see the flurry of set -o.
eval "$flags"      # restore flags

1

আপনি একটি সাব-শেল ব্যবহার করতে পারেন।

(
   set 
   do stuff
)
Other stuff, that set does not apply to
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.