বেশ কয়েকটি কমান্ডের দক্ষতার সাথে বাশ প্রস্থান স্থিতি পরীক্ষা করা হচ্ছে


260

একাধিক কমান্ডের জন্য পাইপফাইলে অনুরূপ কিছু রয়েছে, যেমন 'ট্রাই' স্টেটমেন্টের মতো তবে বাশের মধ্যে। আমি এরকম কিছু করতে চাই:

echo "trying stuff"
try {
    command1
    command2
    command3
}

এবং যে কোনও মুহুর্তে, যদি কোনও কমান্ড ব্যর্থ হয়, ড্রপ আউট এবং সেই আদেশের ত্রুটি প্রতিধ্বনিত হয়। আমি এর মতো কিছু করতে চাই না:

command1
if [ $? -ne 0 ]; then
    echo "command1 borked it"
fi

command2
if [ $? -ne 0 ]; then
    echo "command2 borked it"
fi

এবং আরও ... বা এর মতো কিছু:

pipefail -o
command1 "arg1" "arg2" | command2 "arg1" "arg2" | command3

কারণ আমি বিশ্বাস করি প্রতিটি আদেশের যুক্তিগুলি (আমি ভুল হলে আমাকে সংশোধন করি) একে অপরের সাথে হস্তক্ষেপ করবে। এই দুটি পদ্ধতি আমার কাছে ভয়াবহভাবে দীর্ঘ-বায়ুযুক্ত এবং কদর্য বলে মনে হচ্ছে তাই আমি এখানে আরও দক্ষ পদ্ধতির জন্য আবেদন করছি।


2
দেখে নিন ব্যবহার করার বেসরকারী ব্যাশ কঠোর মোডে : set -euo pipefail
পাবলো এ

1
@ পাবলোবিয়ানচি, set -eএকটি ভয়াবহ ধারণা। ইনশালাম.ডে / scmascheck/various/set এ বিভিন্ন শেল '(এবং শেল সংস্করণ') বাস্তবায়নের মধ্যে অসম্পূর্ণতাগুলি দেখায় এমন তুলনা এবং / বা তুলনামূলকভাবে তুলনা করা বাশফ্যাঙ্ক # 105 এর অনুশীলনগুলি দেখুন different -ই
চার্লস ডাফি

উত্তর:


274

আপনি একটি ফাংশন লিখতে পারেন যা আপনার জন্য আদেশটি প্রবর্তন করে এবং পরীক্ষা করে। ধরে নিন command1এবং command2পরিবেশগত ভেরিয়েবল যা একটি কমান্ডে সেট করা হয়েছে।

function mytest {
    "$@"
    local status=$?
    if (( status != 0 )); then
        echo "error with $1" >&2
    fi
    return $status
}

mytest "$command1"
mytest "$command2"

32
ব্যবহার করবেন না $*, যদি কোনও যুক্তিগুলির মধ্যে ফাঁকা স্থান থাকে তবে তা ব্যর্থ হবে; "$@"পরিবর্তে ব্যবহার করুন। একইভাবে, কমান্ডের $1কোটসের ভিতরে রাখুন echo
গর্ডন ডেভিসন

82
আমি নামটি এড়িয়ে যাব testকারণ এটি একটি অন্তর্নির্মিত কমান্ড।
জন কুগেলম্যান

1
আমি যে পদ্ধতিটি দিয়েছিলাম তা এই। সত্যি কথা বলতে, আমি মনে করি না যে আমি আমার মূল পোস্টে যথেষ্ট পরিস্কার ছিলাম তবে এই পদ্ধতিটি আমাকে আমার নিজের 'পরীক্ষা' ফাংশন লিখতে দেয় যাতে আমি সেখানে ত্রুটিযুক্ত ক্রিয়াকলাপ সম্পাদন করতে পারি যেগুলি এখানে সম্পাদিত ক্রিয়াগুলির সাথে প্রাসঙ্গিক are এই পান্ডুলিপি. ধন্যবাদ :)
jwbensley

7
শেষ কমান্ডটি 'প্রতিধ্বনি' কার্যকর হওয়ার কারণে কোনও ত্রুটির ক্ষেত্রে পরীক্ষার মাধ্যমে প্রস্থানিত কোড () সর্বদা 0 প্রদান করে না? আপনার $ এর মান বাঁচাতে হবে? প্রথম।
ম্যাজিকনায়ার

2
এটি ভাল ধারণা নয় এবং এটি খারাপ অনুশীলনকে উত্সাহ দেয়। এর সাধারণ কেসটি বিবেচনা করুন ls। আপনি যদি অনুরোধ করেন ls fooএবং ফর্মটির একটি ত্রুটি বার্তা পান তবে ls: foo: No such file or directory\nআপনি সমস্যাটি বুঝতে পারেন। পরিবর্তে যদি ls: foo: No such file or directory\nerror with ls\nঅতিরিক্ত অতিরিক্ত তথ্যের দ্বারা আপনি বিভ্রান্ত হন। এই ক্ষেত্রে, তর্ক করা যথেষ্ট সহজ যে অতিমাত্রায় অতি ক্ষুদ্র, তবে এটি দ্রুত বৃদ্ধি পায়। সংক্ষিপ্ত ত্রুটি বার্তা গুরুত্বপূর্ণ। তবে আরও গুরুত্বপূর্ণ বিষয়, এই ধরণের মোড়ক খুব লেখকদের ভাল ত্রুটি বার্তাগুলি সম্পূর্ণরূপে বাদ দিতে উত্সাহ দেয়।
উইলিয়াম পার্সেল

185

"ত্রুটিটি ড্রপ আউট এবং প্রতিধ্বনি" বলতে আপনার কী বোঝায়? যদি আপনি বোঝাতে চান যে কোনও কমান্ড ব্যর্থ হওয়ার সাথে সাথেই আপনি স্ক্রিপ্টটি শেষ করতে চান, তবে ঠিক করুন

set -e    # DON'T do this.  See commentary below.

স্ক্রিপ্টের শুরুতে (তবে নীচে সতর্কতা নোট করুন)। ত্রুটি বার্তা প্রতিধ্বনিত করবেন না: ব্যর্থ কমান্ডটি এটি পরিচালনা করে। অন্য কথায়, যদি আপনি এটি করেন:

#!/bin/sh

set -e    # Use caution.  eg, don't do this
command1
command2
command3

এবং কমান্ড 2 ব্যর্থ হয়, স্টাডারকে একটি ত্রুটি বার্তা প্রিন্ট করার সময়, তখন মনে হয় আপনি যা চান তা অর্জন করেছেন। (যদি না আপনি কী চান তা ভুল ব্যাখ্যা না করে!)

একটি ছদ্মবেশ হিসাবে, আপনার লিখিত যে কোনও কমান্ডটি অবশ্যই ভাল আচরণ করবে: এটি অবশ্যই স্টাডাউটের পরিবর্তে স্ট্ডারকে ত্রুটিগুলি রিপোর্ট করবে (প্রশ্নে থাকা নমুনা কোডটি ত্রুটিগুলি স্ট্যান্ডআউটে প্রিন্ট করে) এবং এটি ব্যর্থ হলে এটি শূন্য-স্থিতি স্থিতির সাথে প্রস্থান করতে হবে।

তবে আমি এটিকে আর একটি ভাল অনুশীলন বলে মনে করি না। set -eবাশ এর বিভিন্ন সংস্করণ দিয়ে এর শব্দার্থবিজ্ঞান পরিবর্তন হয়েছে, এবং যদিও এটি একটি সাধারণ স্ক্রিপ্টের জন্য ভাল কাজ করে, এমন অনেকগুলি প্রান্তের মামলা রয়েছে যা এটি মূলত অকেজো is (এই জাতীয় বিষয়গুলি বিবেচনা করুন: set -e; foo() { false; echo should not print; } ; foo && echo ok এখানে শব্দার্থবিজ্ঞান কিছুটা যুক্তিসঙ্গত, তবে আপনি যদি কোনও ফাংশনটিতে রিফ্যাক্টর কোডটি তাড়াতাড়ি বন্ধ করার অপশন সেটিংয়ের উপর নির্ভর করে থাকেন তবে আপনি সহজেই কামড় পেতে পারেন)) আইএমও লিখতে ভাল:

 #!/bin/sh

 command1 || exit
 command2 || exit
 command3 || exit

অথবা

#!/bin/sh

command1 && command2 && command3

1
পরামর্শ দিন যে এই সমাধানটি সহজতম হলেও এটি আপনাকে ব্যর্থতায় কোনও সাফাই করতে দেয় না।
জোশ জে

6
ফাঁদ দিয়ে পরিষ্কার করা যায়। (যেমন , প্রস্থান করার সময় trap some_func 0কার্যকর some_funcকরা হবে )
উইলিয়াম পার্সেল

3
এছাড়াও লক্ষ করুন যে এরেরেক্সিট (সেট-ই) এর শব্দার্থবিজ্ঞানের বাশের বিভিন্ন সংস্করণে পরিবর্তিত হয়েছে এবং ফাংশন অনুরোধ এবং অন্যান্য সেটিংসের সময় প্রায়শই অপ্রত্যাশিত আচরণ করবেন। আমি আর এর ব্যবহারের পরামর্শ দিচ্ছি না। আইএমও, || exitপ্রতিটি কমান্ডের পরে স্পষ্ট করে লেখাই ভাল ।
উইলিয়াম পার্সেল

87

আমার স্ক্রিপ্টিং ফাংশনগুলির একটি সেট রয়েছে যা আমি আমার রেড হ্যাট সিস্টেমে ব্যাপকভাবে ব্যবহার করি। তারা /etc/init.d/functionsসবুজ [ OK ]এবং লাল [FAILED]স্থিতি সূচকগুলি মুদ্রণের জন্য সিস্টেম ফাংশন ব্যবহার করে ।

$LOG_STEPSকোন কমান্ড ব্যর্থ হয়েছে লগ করতে চাইলে আপনি বৈকল্পিকভাবে একটি লগ ফাইলের নামের সাথে চলকটি সেট করতে পারেন।

ব্যবহার

step "Installing XFS filesystem tools:"
try rpm -i xfsprogs-*.rpm
next

step "Configuring udev:"
try cp *.rules /etc/udev/rules.d
try udevtrigger
next

step "Adding rc.postsysinit hook:"
try cp rc.postsysinit /etc/rc.d/
try ln -s rc.d/rc.postsysinit /etc/rc.postsysinit
try echo $'\nexec /etc/rc.postsysinit' >> /etc/rc.sysinit
next

আউটপুট

Installing XFS filesystem tools:        [  OK  ]
Configuring udev:                       [FAILED]
Adding rc.postsysinit hook:             [  OK  ]

কোড

#!/bin/bash

. /etc/init.d/functions

# Use step(), try(), and next() to perform a series of commands and print
# [  OK  ] or [FAILED] at the end. The step as a whole fails if any individual
# command fails.
#
# Example:
#     step "Remounting / and /boot as read-write:"
#     try mount -o remount,rw /
#     try mount -o remount,rw /boot
#     next
step() {
    echo -n "$@"

    STEP_OK=0
    [[ -w /tmp ]] && echo $STEP_OK > /tmp/step.$$
}

try() {
    # Check for `-b' argument to run command in the background.
    local BG=

    [[ $1 == -b ]] && { BG=1; shift; }
    [[ $1 == -- ]] && {       shift; }

    # Run the command.
    if [[ -z $BG ]]; then
        "$@"
    else
        "$@" &
    fi

    # Check if command failed and update $STEP_OK if so.
    local EXIT_CODE=$?

    if [[ $EXIT_CODE -ne 0 ]]; then
        STEP_OK=$EXIT_CODE
        [[ -w /tmp ]] && echo $STEP_OK > /tmp/step.$$

        if [[ -n $LOG_STEPS ]]; then
            local FILE=$(readlink -m "${BASH_SOURCE[1]}")
            local LINE=${BASH_LINENO[0]}

            echo "$FILE: line $LINE: Command \`$*' failed with exit code $EXIT_CODE." >> "$LOG_STEPS"
        fi
    fi

    return $EXIT_CODE
}

next() {
    [[ -f /tmp/step.$$ ]] && { STEP_OK=$(< /tmp/step.$$); rm -f /tmp/step.$$; }
    [[ $STEP_OK -eq 0 ]]  && echo_success || echo_failure
    echo

    return $STEP_OK
}

এটি খাঁটি সোনার। আমি যখন বুঝতে পারি যে স্ক্রিপ্টটি কীভাবে ব্যবহার করতে হয় আমি প্রতিটি পদক্ষেপ পুরোপুরি উপলব্ধি করতে পারি না, অবশ্যই আমার বাশ স্ক্রিপ্টিং জ্ঞানের বাইরে তবে আমি মনে করি এটি তবুও এটি শিল্পের কাজ।
কিংমিলো

2
এই সরঞ্জামটির কোনও আনুষ্ঠানিক নাম আছে? আমি স্টেপ /
ট্রাই

এই শেল ফাংশনগুলি উবুন্টুতে অনুপলব্ধ বলে মনে হচ্ছে? আমি এটি ব্যবহার করার আশা করছিলাম, যদিও পোর্টেবল কিছু
থোরস্মমনার

@ থারস্মমনার, এটি সম্ভবত কারণ উবুন্টু এসআইএসআইআইআইআই এর পরিবর্তে আপস্টার্ট ব্যবহার করে এবং শীঘ্রই সিস্টেমড ব্যবহার করবে। রেডহ্যাট দীর্ঘ সময়ের জন্য পিছনের দিকে সামঞ্জস্য বজায় রাখে। তাই ডি.ডি.ডি স্টাফ এখনও আছে।
ড্রাগন 788

আমি জন এর সমাধান সম্পর্কে একটি সম্প্রসারণ পোস্ট করেছি এবং এটি উবুন্টুর মতো নন-রেডহ্যাট সিস্টেমে ব্যবহারের অনুমতি দেয়। স্ট্যাকওভারফ্লো.com
মার্ক থমসন

51

এটি মূল্যবান কিসের জন্য, সাফল্যের জন্য প্রতিটি কমান্ড পরীক্ষা করার জন্য কোড লেখার একটি ছোট্ট উপায়:

command1 || echo "command1 borked it"
command2 || echo "command2 borked it"

এটি এখনও ক্লান্তিকর তবে কমপক্ষে এটি পাঠযোগ্য।


আমি ভেবেছিলাম না, যে পদ্ধতিটি নিয়ে আমি গিয়েছিলাম তা নয়, তবে তাড়াতাড়ি এবং সহজেই পড়া সহজ, তথ্যের জন্য ধন্যবাদ :)
jwbensley

3
কমান্ডগুলি নিঃশব্দে কার্যকর করতে এবং একই জিনিস অর্জন করতে:command1 &> /dev/null || echo "command1 borked it"
ম্যাট বাইর্ন

আমি এই পদ্ধতির একজন অনুরাগী, ওআরের পরে একাধিক কমান্ড কার্যকর করার কোনও উপায় আছে কি? এরকম কিছুcommand1 || (echo command1 borked it ; exit)
এন্ড্রেয়াস ক্রাজ

38

একটি বিকল্প হ'ল কমান্ডগুলি একসাথে যোগদান করা &&যাতে ব্যর্থ হওয়া প্রথমটি বাকীটি কার্যকর করতে বাধা দেয়:

command1 &&
  command2 &&
  command3

আপনি যে প্রশ্নটিতে জিজ্ঞাসা করেছেন এটি সিনট্যাক্স নয়, তবে আপনি যে বর্ণনা ব্যবহার করেছেন তার ক্ষেত্রে এটি একটি সাধারণ প্যাটার্ন। সাধারণভাবে কমান্ডগুলি মুদ্রণের ব্যর্থতার জন্য দায়বদ্ধ হওয়া উচিত যাতে আপনাকে ম্যানুয়ালি এটি করতে না হয় ( -qআপনি যখন না চান তখন ত্রুটিগুলি নিঃশব্দ করার জন্য একটি পতাকা দিয়ে)। যদি আপনার এই কমান্ডগুলি সংশোধন করার ক্ষমতা থাকে তবে আমি এগুলিকে অন্য কোনও কিছুতে মোড়ানো না করে ব্যর্থতার চেঁচামেচি করে এডিট করব।


আপনারও করার দরকার নেই তাও লক্ষ করুন:

command1
if [ $? -ne 0 ]; then

আপনি সহজভাবে বলতে পারেন:

if ! command1; then

আর আপনি যখন না চেক করতে হবে প্রত্যাবর্তন কোড পরিবর্তে একটি গাণিতিক প্রসঙ্গ ব্যবহার [ ... -ne:

ret=$?
# do something
if (( ret != 0 )); then

34

রানার ফাংশন তৈরি বা ব্যবহারের পরিবর্তে set -eএকটি ব্যবহার করুন trap:

trap 'echo "error"; do_cleanup failed; exit' ERR
trap 'echo "received signal to stop"; do_cleanup interrupted; exit' SIGQUIT SIGTERM SIGINT

do_cleanup () { rm tempfile; echo "$1 $(date)" >> script_log; }

command1
command2
command3

এমনকি ফাঁদে লাইন নম্বর এবং কমান্ডের কমান্ড লাইনটি অ্যাক্সেস পেয়েছিল যা এটি ট্রিগার করেছিল। ভেরিয়েবলগুলি হ'ল $BASH_LINENOএবং $BASH_COMMAND


4
যদি আপনি আরও চেষ্টা করে চেষ্টা ব্লকটি নকল করতে চান trap - ERRতবে "ব্লক" এর শেষে ফাঁদটি বন্ধ করতে ব্যবহার করুন ।
গর্ডন ডেভিসন

14

ব্যক্তিগতভাবে আমি এখানে হালকা ওজনের পদ্ধতির ব্যবহার পছন্দ করি ;

yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "cannot $*"; }
asuser() { sudo su - "$1" -c "${*:2}"; }

ব্যবহারের উদাহরণ:

try apt-fast upgrade -y
try asuser vagrant "echo 'uname -a' >> ~/.profile"

8
run() {
  $*
  if [ $? -ne 0 ]
  then
    echo "$* failed with exit code $?"
    return 1
  else
    return 0
  fi
}

run command1 && run command2 && run command3

6
দৌড়াবেন না $*, যদি কোনও যুক্তিগুলির মধ্যে ফাঁকা স্থান থাকে তবে তা ব্যর্থ হবে; "$@"পরিবর্তে ব্যবহার করুন। (যদিও echocommand * কমান্ডে ঠিক আছে ))
গর্ডন ডেভিসন

6

আমি প্রায় একটি ত্রুটিবিহীন চেষ্টা এবং বাশে বাস্তবায়ন ধরার বিকাশ করেছি, এটি আপনাকে কোডটি লেখার অনুমতি দেয়:

try 
    echo 'Hello'
    false
    echo 'This will not be displayed'

catch 
    echo "Error in $__EXCEPTION_SOURCE__ at line: $__EXCEPTION_LINE__!"

এমনকি নিজের মধ্যে চেষ্টা করার ব্লকগুলিকে বাসাতে পারেন!

try {
    echo 'Hello'

    try {
        echo 'Nested Hello'
        false
        echo 'This will not execute'
    } catch {
        echo "Nested Caught (@ $__EXCEPTION_LINE__)"
    }

    false
    echo 'This will not execute too'

} catch {
    echo "Error in $__EXCEPTION_SOURCE__ at line: $__EXCEPTION_LINE__!"
}

কোডটি আমার বাশ বয়লারপ্লেট / ফ্রেমওয়ার্কের একটি অংশ । এটি ব্যাকট্র্যাস এবং ব্যতিক্রমগুলি (আরও কিছু সুন্দর বৈশিষ্ট্যগুলি) সহ ত্রুটি পরিচালনা করার মতো জিনিসগুলির সাথে চেষ্টা করার চেষ্টা করার চেষ্টা করে extend

এখানে চেষ্টা এবং ধরার জন্য দায়ী কোডটি এখানে:

set -o pipefail
shopt -s expand_aliases
declare -ig __oo__insideTryCatch=0

# if try-catch is nested, then set +e before so the parent handler doesn't catch us
alias try="[[ \$__oo__insideTryCatch -gt 0 ]] && set +e;
           __oo__insideTryCatch+=1; ( set -e;
           trap \"Exception.Capture \${LINENO}; \" ERR;"
alias catch=" ); Exception.Extract \$? || "

Exception.Capture() {
    local script="${BASH_SOURCE[1]#./}"

    if [[ ! -f /tmp/stored_exception_source ]]; then
        echo "$script" > /tmp/stored_exception_source
    fi
    if [[ ! -f /tmp/stored_exception_line ]]; then
        echo "$1" > /tmp/stored_exception_line
    fi
    return 0
}

Exception.Extract() {
    if [[ $__oo__insideTryCatch -gt 1 ]]
    then
        set -e
    fi

    __oo__insideTryCatch+=-1

    __EXCEPTION_CATCH__=( $(Exception.GetLastException) )

    local retVal=$1
    if [[ $retVal -gt 0 ]]
    then
        # BACKWARDS COMPATIBILE WAY:
        # export __EXCEPTION_SOURCE__="${__EXCEPTION_CATCH__[(${#__EXCEPTION_CATCH__[@]}-1)]}"
        # export __EXCEPTION_LINE__="${__EXCEPTION_CATCH__[(${#__EXCEPTION_CATCH__[@]}-2)]}"
        export __EXCEPTION_SOURCE__="${__EXCEPTION_CATCH__[-1]}"
        export __EXCEPTION_LINE__="${__EXCEPTION_CATCH__[-2]}"
        export __EXCEPTION__="${__EXCEPTION_CATCH__[@]:0:(${#__EXCEPTION_CATCH__[@]} - 2)}"
        return 1 # so that we may continue with a "catch"
    fi
}

Exception.GetLastException() {
    if [[ -f /tmp/stored_exception ]] && [[ -f /tmp/stored_exception_line ]] && [[ -f /tmp/stored_exception_source ]]
    then
        cat /tmp/stored_exception
        cat /tmp/stored_exception_line
        cat /tmp/stored_exception_source
    else
        echo -e " \n${BASH_LINENO[1]}\n${BASH_SOURCE[2]#./}"
    fi

    rm -f /tmp/stored_exception /tmp/stored_exception_line /tmp/stored_exception_source
    return 0
}

বিনামূল্যে ব্যবহার করুন, কাঁটাচামচ করুন এবং অবদান রাখুন - এটি গিটহাবের মধ্যে রয়েছে


1
আমি রেপুর দিকে তাকিয়েছি এবং এটি নিজেই ব্যবহার করব না, কারণ এটি আমার স্বাদে অনেক বেশি যাদু রয়েছে (আইএমও যদি আরও বিমূর্ত শক্তি প্রয়োজন তবে পাইথন ব্যবহার করা আরও ভাল) তবে অবশ্যই আমার থেকে বড় +1 কারণ এটি দেখতে কেবল দুর্দান্ত লাগে।
আলেকজান্ডার মালাখভ

দয়া করে @ আলেকজান্ডারমালাখভ এই শব্দটির জন্য ধন্যবাদ। আমি "ম্যাজিক" এর পরিমাণ সম্পর্কে একমত - এটি একটি কারণ যা আমরা ফ্রেমওয়ার্কের একটি সরলীকৃত 3.0 সংস্করণ বুদ্ধিদীপ্ত করছি, যা বোঝা, ডিবাগ করা সহজ হবে ইত্যাদি G জিএইচ সম্পর্কে 3.0 সম্পর্কে একটি উন্মুক্ত সমস্যা আছে, যদি আপনি আপনার চিন্তায় চিপ করতে চাই
নিনিয়ান

3

দুঃখিত যে আমি প্রথম উত্তরে মন্তব্য করতে পারি না তবে কমান্ডটি কার্যকর করতে আপনার নতুন উদাহরণটি ব্যবহার করা উচিত: সেমিড_আউটপুট = $ ($ @)

#!/bin/bash

function check_exit {
    cmd_output=$($@)
    local status=$?
    echo $status
    if [ $status -ne 0 ]; then
        echo "error with $1" >&2
    fi
    return $status
}

function run_command() {
    exit 1
}

check_exit run_command

2

জন্য মাছ শেল ব্যবহারকারী এই থ্রেডে পদস্খলন।

আসুন fooএমন একটি ফাংশন হয়ে উঠুন যা কোনও মান "রিটার্ন" (প্রতিধ্বনি) না করে তবে এটি প্রস্থান কোডটি যথারীতি সেট করে। ফাংশন কল করার পরে
চেক এড়াতে $status, আপনি এটি করতে পারেন:

foo; and echo success; or echo failure

এবং যদি এটি খুব দীর্ঘ হয় তবে একটি লাইনে ফিট করতে:

foo; and begin
  echo success
end; or begin
  echo failure
end

1

আমি যখন ব্যবহার sshকরি তখন আমার সংযোগ সমস্যা এবং errexit( set -e) মোডে রিমোট কমান্ডের ত্রুটি কোডগুলির কারণে সৃষ্ট সমস্যাগুলির মধ্যে পার্থক্য করা উচিত । আমি নিম্নলিখিত ফাংশন ব্যবহার:

# prepare environment on calling site:

rssh="ssh -o ConnectionTimeout=5 -l root $remote_ip"

function exit255 {
    local flags=$-
    set +e
    "$@"
    local status=$?
    set -$flags
    if [[ $status == 255 ]]
    then
        exit 255
    else
        return $status
    fi
}
export -f exit255

# callee:

set -e
set -o pipefail

[[ $rssh ]]
[[ $remote_ip ]]
[[ $( type -t exit255 ) == "function" ]]

rjournaldir="/var/log/journal"
if exit255 $rssh "[[ ! -d '$rjournaldir/' ]]"
then
    $rssh "mkdir '$rjournaldir/'"
fi
rconf="/etc/systemd/journald.conf"
if [[ $( $rssh "grep '#Storage=auto' '$rconf'" ) ]]
then
    $rssh "sed -i 's/#Storage=auto/Storage=persistent/' '$rconf'"
fi
$rssh systemctl reenable systemd-journald.service
$rssh systemctl is-enabled systemd-journald.service
$rssh systemctl restart systemd-journald.service
sleep 1
$rssh systemctl status systemd-journald.service
$rssh systemctl is-active systemd-journald.service

1

আপনি @ জন-কুগলম্যানের অ-রেডহ্যাট সিস্টেমগুলিতে তার কোডটিতে এই লাইনটি মন্তব্য করে উপরে যে দুর্দান্ত সমাধান পেয়েছেন তা ব্যবহার করতে পারেন :

. /etc/init.d/functions

তারপরে, নীচে কোডটি পেস্ট করুন। সম্পূর্ণ প্রকাশ: এটি সেন্টোস 7 থেকে নেওয়া উল্লিখিত ফাইলটির প্রাসঙ্গিক বিটগুলির কেবল একটি সরাসরি অনুলিপি এবং আটকানো।

MacOS এবং উবুন্টু 18.04 এ পরীক্ষিত।


BOOTUP=color
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"

echo_success() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
    echo -n $"  OK  "
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 0
}

echo_failure() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
    echo -n $"FAILED"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
}

echo_passed() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo -n $"PASSED"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
}

echo_warning() {
    [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
    echo -n "["
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo -n $"WARNING"
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "]"
    echo -ne "\r"
    return 1
} 

0

কার্যক্ষম পদ্ধতিতে স্থিতি পরীক্ষা করা হচ্ছে

assert_exit_status() {

  lambda() {
    local val_fd=$(echo $@ | tr -d ' ' | cut -d':' -f2)
    local arg=$1
    shift
    shift
    local cmd=$(echo $@ | xargs -E ':')
    local val=$(cat $val_fd)
    eval $arg=$val
    eval $cmd
  }

  local lambda=$1
  shift

  eval $@
  local ret=$?
  $lambda : <(echo $ret)

}

ব্যবহার:

assert_exit_status 'lambda status -> [[ $status -ne 0 ]] && echo Status is $status.' lls

আউটপুট

Status is 127
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.