5 বার পর্যন্ত চালানোর জন্য পুনরায় চেষ্টা করতে আমি কীভাবে স্ক্রিপ্টে পুনরায় চেষ্টা করার যুক্তি লিখব?


112

আমি শেল স্ক্রিপ্টে যুক্তি লিখতে চাই যা এটি "স্ট্যাটাস কোড = ফেইল " এর ভিত্তিতে 5 বার পর্যন্ত 15 সেকেন্ডের পরে আবার চালানোর জন্য আবার চেষ্টা করবে যদি এটি কোনও সমস্যার কারণে ব্যর্থ হয়।

উত্তর:


90

এই স্ক্রিপ্টটি nপাঁচটিতে কমান্ডের প্রচেষ্টা সীমাবদ্ধ করতে একটি কাউন্টার ব্যবহার করে । কমান্ডটি সফল $?হলে শূন্যটি ধরে রাখবে এবং লুপ থেকে কার্যকর হবে।

n=0
until [ $n -ge 5 ]
do
   command && break  # substitute your command here
   n=$[$n+1]
   sleep 15
done

1
আপনার যোগ করা উচিত breakযদি কমান্ড সফল হয় তবে তা লুপটি ভেঙে দেবে
রাহুল পাতিল

প্রকৃতপক্ষে এটি লেখার যথাযথ উপায় if command; then break; fiবা আরও command && break
সংজ্ঞায়িতভাবে

1
"কমান্ড" হ'ল কমান্ডের নাম যা আপনি স্থিতিটি পরীক্ষা করতে চান।
সন্দেহভাজন

3
আপনি যে কমান্ড সফল হয়েছে কিনা তা জানতে n শেষে পাঁচটির সমান হলে পরীক্ষা করতে পারবেন তা লক্ষণীয়।
ম্যাচটিএম

4
চমৎকার সমাধান - তবে nব্যর্থতার ক্ষেত্রে, বাহ্যিকভাবে বের হওয়ার আগে এটি অযথা আরও একটি সময় ঘুমায়।
রন রোথম্যান

126
for i in 1 2 3 4 5; do command && break || sleep 15; done

আপনার আদেশ দ্বারা "কমান্ড" প্রতিস্থাপন করুন। এটি ধরে নেওয়া হচ্ছে যে "স্থিতি কোড = FAIL" এর অর্থ কোনও শূন্য নয় এমন রিটার্ন কোড।


প্রকারভেদ:

{..}বাক্য গঠন ব্যবহার করে । বেশিরভাগ শেলগুলিতে কাজ করে তবে ব্যাসিবক্স নয় sh:

for i in {1..5}; do command && break || sleep 15; done

seqব্যর্থ কমান্ডের প্রস্থান কোডটি ব্যবহার এবং পাশ করা:

for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)

উপরের মতো একই, তবে sleep 15চূড়ান্ত ব্যর্থতার পরে এড়িয়ে যাওয়া । যেহেতু একবারে কেবলমাত্র সর্বোচ্চ সংখ্যক লুপ সংজ্ঞায়িত করা ভাল, লুপের শুরুতে ঘুমানোর মাধ্যমে এটি অর্জন করা যায় যদি i > 1:

for i in $(seq 1 5); do [ $i -gt 1 ] && sleep 15; command && s=0 && break || s=$?; done; (exit $s)

25
+1 - সংক্ষিপ্ত এবং পরিষ্কার। এক পরামর্শ: আমি প্রতিস্থাপন করবে for i in 1 2 3 4 5সঙ্গে for i in {1..5}কারণ এটি বজায় রাখার জন্য আরো সহজ।
ধানের ল্যান্ডাউ

5
কেবল একটি নোট, এটি কাজ &&করে ||কারণ অপারেটর অগ্রাধিকারের
জিন_উড

6
অন্য নোট, এটি commandব্যর্থ হলেও এমনকি কোড 0 ফিরিয়ে দেবে ।
হেনরিক জ্যাম্বন

3
@ হেনরিক জ্যাম্বন একটি সংস্করণ যুক্ত করেছে যা এটিরও পরিচালনা করে।
আলেকজান্ডার

2
চূড়ান্ত ব্যর্থতার পরে এই ঘুম হয় না? অপ্রয়োজনীয় 15 অপেক্ষা অপেক্ষা মনে হচ্ছে। আমি মনে করি [[ i -eq 5]]এটি এড়ানোর জন্য আপনি ঘুমের আগে একটি ওআর শর্ত হিসাবে একটি চেক রাখতে পারেন ।
ডেভ লাগেজ

32
function fail {
  echo $1 >&2
  exit 1
}

function retry {
  local n=1
  local max=5
  local delay=15
  while true; do
    "$@" && break || {
      if [[ $n -lt $max ]]; then
        ((n++))
        echo "Command failed. Attempt $n/$max:"
        sleep $delay;
      else
        fail "The command has failed after $n attempts."
      fi
    }
  done
}

উদাহরণ:

retry ping invalidserver

এই আউটপুট উত্পাদন করে:

ping: unknown host invalidserver
Command failed. Attempt 2/5:
ping: unknown host invalidserver
Command failed. Attempt 3/5:
ping: unknown host invalidserver
Command failed. Attempt 4/5:
ping: unknown host invalidserver
Command failed. Attempt 5/5:
ping: unknown host invalidserver
The command 'ping invalidserver' failed after 5 attempts

একটি বাস্তব-জগতের জন্য, জটিল কমান্ড সহ কার্যকারী উদাহরণ, এই স্ক্রিপ্টটি দেখুন


3
এটি একটি দুর্দান্ত সমাধান। আমি পছন্দ করি যে এটি কোনও একাধিকবার ব্যর্থ হওয়ার পরে এটি শূন্য-বহির্গমন প্রস্থানের সাথে প্রস্থান করে।
বেন লিয়ানাজ

11

পুনরায় চেষ্টা করার জন্য এখানে ফাংশন

function retry()
{
        local n=0
        local try=$1
        local cmd="${@: 2}"
        [[ $# -le 1 ]] && {
        echo "Usage $0 <retry_number> <Command>"; }

        until [[ $n -ge $try ]]
        do
                $cmd && break || {
                        echo "Command Fail.."
                        ((n++))
                        echo "retry $n ::"
                        sleep 1;
                        }

        done
}

retry $*

আউটপুট:

[test@Nagios ~]$ ./retry.sh 3 ping -c1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.207 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.207/0.207/0.207/0.000 ms

[test@Nagios ~]$ ./retry.sh 3 ping -c1 localhostlasjflasd
ping: unknown host localhostlasjflasd
Command Fail..
retry 1 ::
ping: unknown host localhostlasjflasd
Command Fail..
retry 2 ::
ping: unknown host localhostlasjflasd
Command Fail..
retry 3 ::

আমি আপনার কোডটি পুনরায় চেষ্টা করুন নতুন ফাইলটিতে পেস্ট করেছি এবং শীর্ষে একটি লাইন #! / বিন / বাশ যুক্ত করেছি। আপনার প্রদত্ত আদেশগুলি ব্যাখ্যায় দৌড়ানোর সময় আমি আর কিছু প্রম্পট দেখি না again
java_enthu

আপনি কি চেষ্টা করেছেনbash retry.sh 3 ping -c1 localhost
রাহুল পাতিল

হ্যাঁ রাহুল আমি চেষ্টা করেছিলাম।
java_enthu

দুঃখিত, আমি bizy .., আমি আবার পরীক্ষা আছে ছিল, এটা কাজ, আউটপুট পরীক্ষা paste.ubuntu.com/6002711
রাহুল পাতিল

এটি এখন পর্যন্ত এখানে সর্বাধিক মার্জিত উত্তর - আপনি যদি অ-তুচ্ছ কিছু করেন। সময় দেবার জন্য ধন্যবাদ।
জেরি অ্যান্ড্রুজ


5

এখানে আমার প্রিয় এক লাইন ওরফে / স্ক্রিপ্ট

    alias retry='while [ $? -ne 0 ] ; do fc -s ; done'

তারপরে আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

     $ ps -ef | grep "Next Process"
     $ retry

এটি "পরবর্তী প্রক্রিয়া" না পাওয়া পর্যন্ত এটি পূর্ববর্তী কমান্ডটি চালিয়ে যাবে


1
Zsh এ, এর fc -e "#"পরিবর্তে ব্যবহার করুন fc -s
রিকার্ডো স্টুভেন

2

আমি এই স্ক্রিপ্টটি ব্যবহার করি যা প্রদত্ত কমান্ডের পুনরায় চেষ্টা করে, এই স্ক্রিপ্টের সুবিধাটি হ'ল যদি সমস্ত পুনরায় চেষ্টা ব্যর্থ হয় তবে এটি প্রস্থান কোডটি সংরক্ষণ করবে।

#!/usr/bin/env bash

if [ $# -ne 3 ]; then
    echo 'usage: retry <num retries> <wait retry secs> "<command>"'
    exit 1
fi

retries=$1
wait_retry=$2
command=$3

for i in `seq 1 $retries`; do
    echo "$command"
    $command
    ret_value=$?
    [ $ret_value -eq 0 ] && break
    echo "> failed with $ret_value, waiting to retry..."
    sleep $wait_retry
done

exit $ret_value

সম্ভবত এটি আরও সহজ পেতে পারেন


আমি পছন্দ করি যে এই সংস্করণটি কতটা নমনীয় এবং কোডটি ভার্বোস এবং পাঠযোগ্য!
yo.ian.g 12

ব্যর্থ প্রতিধ্বনি মেলে আপনি এমনকি [$ ret_value -eq 0] এর সাথে একটি সফল প্রতিধ্বনি যুক্ত করতে পারেন বা পরে $ ret_value পরীক্ষা করতে পারবেন
yo.ian.g

এই সংস্করণটি শেষবার কমান্ড ব্যর্থ হওয়ার পরে না ঘুমানোর সুবিধা রয়েছে has
আলেকজান্ডার

1

নীচে দেখুন উদাহরণ:

n=0
while :
do
        nc -vzw1 localhost 3859
        [[ $? = 0 ]] && break || ((n++))
        (( n >= 5 )) && break

done

আমি লোকালহোস্টে 3389 বন্দরটি সংযোগ দেওয়ার চেষ্টা করছি, এটি 5 বার ব্যর্থ হওয়া পর্যন্ত পুনরায় চেষ্টা করবে, যদি সাফল্য হয় তবে এটি লুপটি ভেঙে দেবে।

$? এটি কমান্ডের স্থিতি যদি শূন্য মানে কমান্ড সফলভাবে চালিত হয়, যদি শূন্য ব্যতীত অন্য কমান্ড ফাই হয়

কিছুটা জটিল বলে মনে হচ্ছে, কেউ এর চেয়ে ভাল এটি করতে পারে।


ধন্যবাদ রাহুল .. স্ক্রিপ্টটি চালানোর জন্য কি আবার চেষ্টা করা হবে ??
সন্দীপ সিং

দয়া করে এখনই পরীক্ষা করুন, আমি আপডেট করেছি
রাহুল পাতিল

$?এটি শূন্যের অর্থ কমান্ড সফলভাবে পরিচালিত হলে কমান্ডের স্থিতি রয়েছে, শূন্য ব্যতীত যদি কমান্ড ব্যর্থ হয়
রাহুল পাতিল

এটি হোস্ট এবং পোর্ট ঠিকানা দিতে প্রয়োজন? আমরা কি স্ক্রিপ্টের অবস্থান দির দিয়ে এটি করতে পারি?
সন্দীপ সিং

প্রস্থান স্থিতি কোড দেয় যে কোনও কমান্ড সঙ্গে প্রতিস্থাপন?
রাহুল পাতিল

1

আপনি এখানেloop কমান্ডটি এখানে উপলভ্য ব্যবহার করতে পারেন :

$ loop './do_thing.sh' --every 15s --until-success --num 5 

যা আপনার কাজটি সাফল্য না হওয়া পর্যন্ত প্রতি 15 সেকেন্ডে সর্বোচ্চ পাঁচ বার করবে।


0

retryফাংশনাল প্রোগ্রামিং পিউরিস্টদের জন্য এখানে একটি পুনরাবৃত্ত ফাংশন রয়েছে:

retry() {
  cmd=$1
  try=${2:-15}       # 15 by default
  sleep_time=${3:-3} # 3 seconds by default

  # Show help if a command to retry is not specified.
  [ -z "$1" ] && echo 'Usage: retry cmd [try=15 sleep_time=3]' && return 1

  # The unsuccessful recursion termination condition (if no retries left)
  [ $try -lt 1 ] && echo 'All retries failed.' && return 1

  # The successful recursion termination condition (if the function succeeded)
  $cmd && return 0

  echo "Execution of '$cmd' failed."

  # Inform that all is not lost if at least one more retry is available.
  # $attempts include current try, so tries left is $attempts-1.
  if [ $((try-1)) -gt 0 ]; then
    echo "There are still $((try-1)) retrie(s) left."
    echo "Waiting for $sleep_time seconds..." && sleep $sleep_time
  fi

  # Recurse
  retry $cmd $((try-1)) $sleep_time
}

এটি একটি আদেশ (বা একটি ফাংশন নাম) এবং allyচ্ছিকভাবে অনেকগুলি পুনরায় চেষ্টা এবং পুনরায় চেষ্টাগুলির মধ্যে একটি ঘুমের সময়কাল পাস করুন:

retry some_command_or_fn 5 15 # 5 tries, sleep 15 seconds between each

এটি কমান্ডের জন্য একাধিক শব্দের বেশি দীর্ঘ ব্যবহার করে না: সেমিডি = "ইকো ব্লা ব্লাহ" ... লাইন 10: [: ব্লাহ: পূর্ণসংখ্যার এক্সপ্রেশন প্রত্যাশিত ... এটি পাইপ ইত্যাদির
জন্যও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.