লুপের ফলাফলের ভিত্তিতে আমি কীভাবে এই স্ক্রিপ্টটিকে ত্রুটি থেকে বেরিয়ে যেতে পারি?


13

আমার একটি বাশ স্ক্রিপ্ট রয়েছে যা ব্যবহার করে set -o errexitযাতে ত্রুটিযুক্ত হয়ে পুরো স্ক্রিপ্টটি ব্যর্থতার পয়েন্টে উপস্থিত হয়।
স্ক্রিপ্টটি একটি curlকমান্ড চালায় যা কখনও কখনও উদ্দিষ্ট ফাইলটি পুনরুদ্ধার করতে ব্যর্থ হয় - তবে যখন এটি ঘটে তখন স্ক্রিপ্টটি প্রস্থান করতে ত্রুটি করে না।

আমি একটি forলুপ যুক্ত করেছি

  1. কয়েক সেকেন্ডের জন্য বিরতি দিন তারপর curlকমান্ডটি আবার চেষ্টা করুন
  2. falseডিফল্ট অ-শূন্য প্রস্থান স্থিতি সংজ্ঞায়িত করতে লুপের নীচে ব্যবহার করুন - কার্ল কমান্ড সফল হলে - লুপটি বিরতি এবং শেষ কমান্ডের প্রস্থান স্থিতি শূন্য হওয়া উচিত।
#! /bin/bash

set -o errexit

# ...

for (( i=1; i<5; i++ ))
do
    echo "attempt number: "$i
    curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
    if [ -f ~/.vim/autoload/pathogen.vim ]
    then
        echo "file has been retrieved by curl, so breaking now..."
        break;
    fi

    echo "curl'ed file doesn't yet exist, so now will wait 5 seconds and retry"
    sleep 5
    # exit with non-zero status so main script will errexit
    false

done

# rest of script .....

সমস্যাটি যখন curlকমান্ড ব্যর্থ হয়, লুপটি পাঁচবার কমান্ডটি পুনরায় চেষ্টা করে - যদি সমস্ত প্রচেষ্টা ব্যর্থ হয় তবে লুপ শেষ হওয়ার জন্য এবং মূল স্ক্রিপ্টটি পুনরায় শুরু হয় - পরিবর্তে ট্রিগার না করে errexit
এই curlবিবৃতি ব্যর্থ হলে আমি কীভাবে পুরো স্ক্রিপ্টটি প্রস্থান করতে পারি?

উত্তর:


18

প্রতিস্থাপন করুন:

done

সঙ্গে:

done || exit 1

forলুপটি যদি কোনও শূন্য-বহির্গমন কোডের সাথে প্রস্থান করে তবে কোডটি প্রস্থান করবে।

তুচ্ছ বস্তু একটি বিন্দু হিসাবে, 1exit 1প্রয়োজন হয় না। একটি প্লেইন exitকমান্ড সর্বশেষ নির্বাহিত কমান্ডের প্রস্থান স্থিতি দিয়ে প্রস্থান করবে যা falseডাউনলোড ব্যর্থ হলে এটি হবে (কোড = 1)। ডাউনলোডটি সফল হলে লুপের প্রস্থান কোড হ'ল echoকমান্ডের প্রস্থান কোড । echoসাধারণত কোড = 0 দিয়ে প্রস্থান করে, সাফল্যের সাথে সাফল্য। সেক্ষেত্রে ||, ট্রিগার হয় না এবং exitকমান্ড কার্যকর হয় না।

সবশেষে, দ্রষ্টব্য যে set -o errexitআশ্চর্য পূর্ণ হতে পারে। এর পক্ষে মতামত নিয়ে আলোচনার জন্য গ্রেগের FAQ # 105 দেখুন

নথিপত্র

থেকে man bash:

জন্য (; expr2; expr3) (expr1); কি তালিকা; সম্পন্ন
প্রথমত, গাণিতিক এক্সপ্রেশন এক্সপি 1 এরিথমেটিক মূল্যায়নের অধীনে নীচে বর্ণিত বিধি অনুসারে মূল্যায়ন করা হয়। পাটিগণিতের এক্সপ্রেশন এক্সপ্র 2 এর পরে বারবার মূল্যায়ন করা হয় যতক্ষণ না এটি শূন্যের মূল্যায়ন করে। প্রতিবার এক্সপ্রেস 2 অ-শূন্য মানের মান নির্ধারণ করে, তালিকাটি কার্যকর করা হয় এবং গাণিতিক এক্সপ্রেশন এক্সপ্রে 3 মূল্যায়ন করা হয়। যদি কোনও অভিব্যক্তি বাদ দেওয়া হয় তবে এটি এটি 1 এর মূল্যায়নের মতো আচরণ করে The প্রত্যাবর্তন মান হ'ল তালিকার শেষ কমান্ডের প্রস্থান স্থিতি যা কার্যকর করা হয়, বা কোনও অভিব্যক্তি অবৈধ হলে তা মিথ্যা। [সামনে জোর দাও]


আপনি কি মনে করেন trueযে ব্রেক স্টেটমেন্টটি স্পষ্ট করে দেওয়া এবং লুপটির প্রস্থান মূল্য নিশ্চিত করা আগে রাখা ভাল ধারণা হবে?
রবার্টএল

1
আমি মনে করি যে স্পষ্ট বর্ণিত চেয়ে ভাল । এই কারণেই আমি লিখেছিলাম exit 1যখন কেবল সরল exitকাজ করবে। এটি শৈলীর একটি প্রশ্ন এবং অন্যদের নিজস্ব মতামত থাকতে পারে।
1024

1
সুন্দরভাবে কাজ করে! ধন্যবাদ :) ব্যক্তিগতভাবে আমি exitসরল প্রস্থান হিসাবে পড়ব - যা স্ক্রিপ্টটিকে তার নিজের ডানদিকে সমাপ্ত করে। exit 1 অন্য কিছু প্রক্রিয়াতে (যেমন errexit) "সিগন্যাল" হিসাবে আমার কাছে পড়তেন - এটির "ফলাফল" এর উপর ভিত্তি করে স্ক্রিপ্টটি শেষ করা উচিত exit 1। - তাই আমি সাথে গিয়েছি exitতবে ব্যাখ্যার জন্য ধন্যবাদ
the_velour_fog

1
যদি আপনার স্ক্রিপ্টটি ত্রুটির শর্তের কারণে প্রস্থান করা হয়, আপনার কল করা উচিতexit 1 । এটি মোটেই প্রভাবিত করে না errexit। এটি কেবল কলিং প্রোগ্রামকে বলে যে কিছু ভুল হয়েছে। falseকমান্ড এক বিবৃতিতে রয়েছে: exit(1)। ইউনিক্স কমান্ডের 99.9% সাফল্যে 0 এবং ত্রুটি-শূন্য-তে ফিরে আসে। তোমারও উচিত
রবার্টএল

2

আপনি যদি errexitসেট করে falseরেখেছেন , তাহলে বিবৃতিটির সাথে সাথে স্ক্রিপ্টটি অবিলম্বে প্রস্থান করা উচিত। curlআদেশটি ব্যর্থ হলে একই জিনিস ।

আপনি যেমন চিত্রনাট্য হিসাবে লিখিত, প্রথম curlকমান্ড ব্যর্থতার পরে প্রস্থান করা উচিত যখন প্রথমবার falseএটিরেক্সট সেট করা থাকে তখন কল হয়।

এটি কীভাবে কাজ করে তা দেখতে ( -eসেট করার জন্য আমি শর্টহ্যান্ড ব্যবহার করি errexit:

$ ( set -e;  false; echo still here )
$

$ ( set +e;  false; echo still here )
still here
$

সুতরাং যদি curlকমান্ডটি একাধিকবার কার্যকর করে, এই স্ক্রিপ্টটি errexitসেট করে না ।


1
set -eতার চেয়ে আরও সূক্ষ্ম। এটি একটি লুপে প্রথম ব্যর্থ কমান্ডের পরে প্রস্থান করবে না(set -e; for (( i=1; i<5; i++ )); do echo $i; false; done || echo "FAIL"; )কোডটি falseচারবার চলে বলে মনে করে আপনি এটি চালিয়ে যেতে পারেন । আরও তথ্যের জন্য set -e, গ্রেগের FAQ # 105 দেখুন
1024

@ জন 1024 ধন্যবাদ এটি নীচে এবং বাইরে নিচে যাচ্ছে।
রবার্টল

@ জন 1024 তবে আমি অনুমান করি যে প্রমাণগুলি এখনও errexitসেট করা হয়নি। প্রশ্নের স্ক্রিপ্টে যুক্তি প্রয়োগ করুন। এটি চালান: (set -e; for (( i=1; i<5; i++ )); do echo $i; false; done ; echo still here ) হ্যাঁ if while || &&ইত্যাদির সাথে রিটার্ন মানগুলি পরীক্ষা করা ত্রুটিযুক্ত করে না। মূল স্ক্রিপ্ট ||লুপের জন্য করেনি ।
রবার্টএল

আমি কেবল লক্ষ্য করেছি যে আমি set -o errexitআমার উদাহরণ কোডটিতে কমান্ডটি দেখিনি , এখনই এটি যুক্ত করেছি - এবং আমার জন্য এটি প্রত্যাশার সাথে বেরিয়ে যাওয়ার ত্রুটি ছিল না। falseলুপের জন্য আমার সর্বশেষ কমান্ড হিসাবে রাখা দরকার ছিল , তারপরে লুপটি বন্ধ করুন done || exit [1]- তবে এটি দুর্দান্তভাবে কাজ করেছিল!
the_velour_fog

@ রবার্টল আমি আপনার বক্তব্যটি দেখতে পাচ্ছি।
1024

1

set -o errexit লুপস এবং সাবশেলের ক্ষেত্রে জটিল হতে পারে, কারণ আপনাকে প্রক্রিয়াটি থেকে বেরিয়ে আসতে হবে।

একটি লুপ ভাঙ্গা (এমনকি সাধারণ অপারেশনেও) খারাপ অভ্যাস হিসাবে বিবেচিত হয়। আপনি দুটি শর্তের জন্য ফর-লুপের চেয়ে কিছুক্ষণের জন্য লুপ পছন্দ করতে আমাকে ওল্ড-স্কুল বলতে পারেন, তবে পড়তে ভাল লাগবে:

i=1
RET=-1
while [ $i -le 5 ] && [ $RET -ne 0 ]; do
    [ $i -eq 1 ] || sleep 5
    echo "attempt number: "$i
    curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
    RET=$?
    i=$((i+1))
done
exit $RET

0

যদি errexitসেট করা থাকে এবং curlকমান্ডটি ব্যর্থ কার্ল কমান্ডের ঠিক পরে স্ক্রিপ্টটি সমাপ্ত হয়। বাশ ম্যানুয়ালটিতে কোনও ইঙ্গিত নেই যা set -eএকটি যৌগিক কমান্ডে কোনও একক এর ব্যর্থ রিটার্নের অবস্থা উপেক্ষা করে। এটি কেবল তখনই ঘটতে পারে যখন সম্মত কমান্ডটি এমন একটি প্রেক্ষাপটে কার্যকর করা হয় যেখানে set -eউপেক্ষা করা হয়।
https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin

রবার্টএল পোস্ট করা কিছুটা অভিযোজিত উদাহরণ চেষ্টা করুন। এটি মিথ্যা কমান্ডের ঠিক পরে পুনরাবৃত্তির প্রথম স্থানে থামবে:

( set -e; for (( i=1; i<5; i++ )); do echo $i; false; echo "${i}. iteration done"; done ; echo "loop done" )

0

আপনি কেবল কার্ল কমান্ডে --fail বিকল্পটি যুক্ত করতে পারেন, এটি আপনার সমস্যার সমাধান করবে, স্ক্রিপ্টটি ব্যর্থ হবে এবং কার্ল কমান্ড ব্যর্থ হলে ত্রুটি থেকে বেরিয়ে যাবে, জেনকিনস পাইপলাইনে কার্ল ব্যবহার করার সময় খুব কার্যকর যদি:

curl -LSso --fail ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.