অপ্রয়োজনীয় দেরি না করে ব্যাশে একটি কমান্ডের সমাপ্তি


283

নির্দিষ্ট সময়ের পরে কোনও কমান্ডকে স্ব-হত্যা করতে কমান্ড লাইন কমান্ডের এই উত্তর

ব্যাশ কমান্ড লাইন থেকে দীর্ঘ-চলমান কমান্ডের সময়সীমা নির্ধারণের জন্য একটি 1-লাইন পদ্ধতি প্রস্তাব করে:

( /path/to/slow command with options ) & sleep 5 ; kill $!

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

সুতরাং এই নিফটি 1-লাইন পদ্ধতির বেশ কয়েকটি সমস্যা রয়েছে। প্রথমত, sleepশর্তসাপেক্ষ নয়, যাতে ক্রমটি শেষ হওয়ার জন্য নেওয়া সময়টির উপর একটি অনাকাঙ্ক্ষিত নিম্ন বাউন্ড সেট করে। 30s বা 2m বা এমনকি 5m ঘুমের জন্য বিবেচনা করুন, যখন tlrbsf কমান্ড 2 সেকেন্ডের মধ্যে শেষ হয় - অত্যন্ত অনাকাঙ্ক্ষিত। দ্বিতীয়ত, এটি killনিঃশর্ত, সুতরাং এই ক্রমটি একটি চলমান প্রক্রিয়াটিকে মেরে ফেলার চেষ্টা করবে এবং এটি সম্পর্কে কৌতুক করবে।

তাই ...

একটি সাধারণত-দীর্ঘ-চলমান-তবে-কখনও কখনও দ্রুত ( "tlrbsf" ) কমান্ডের টাইমআউট করার কোনও উপায় আছে যা

  • বাশ বাস্তবায়ন রয়েছে (অন্য প্রশ্নের মধ্যে ইতিমধ্যে পার্ল এবং সি উত্তর রয়েছে)
  • দুটির প্রথমদিকে সমাপ্ত হবে: tlrbsf প্রোগ্রামের সমাপ্তি, বা সময়সীমা অতিক্রান্ত
  • অ-বিদ্যমান / অ-চলমান প্রক্রিয়াগুলিকে হত্যা করবে না (বা, বিকল্পভাবে: খারাপ কিল সম্পর্কে অভিযোগ করবে না )
  • 1-লাইনার হতে হবে না
  • সাইগউইন বা লিনাক্সের অধীনে চলতে পারে

... এবং, বোনাস পয়েন্টগুলির জন্য, অগ্রভাগে tlrbsf কমান্ড এবং পটভূমিতে কোনও 'স্লিপ' বা অতিরিক্ত প্রক্রিয়া চালিত করে , যেমন tlrbsf কমান্ডের stdin / stdout / stderr পুনঃনির্দেশিত করা যেতে পারে, যেমন এটি হয়েছে সরাসরি চালাবেন?

যদি তা হয় তবে আপনার কোডটি শেয়ার করুন। যদি না হয়, কেন তা ব্যাখ্যা করুন।

আমি উপরোক্ত উদাহরণটি হ্যাক করার জন্য কিছুটা সময় ব্যয় করেছি তবে আমি আমার বাশ দক্ষতার সীমাটি আঘাত করছি।


5
আরেকটি অনুরূপ প্রশ্ন: stackoverflow.com/questions/526782/... (কিন্তু আমি মনে করি 'timeout3' উত্তর এখানে অনেক ভালো)।
সিস্টেম PAUSE

2
Gnu timeoutইউটিলিটি ব্যবহার না করার কোনও কারণ ?
ক্রিস জনসন

timeoutমহান! আপনি একাধিক কমান্ড (মাল্টি-লাইন স্ক্রিপ্ট) দিয়েও ব্যবহার করতে পারেন : stackoverflow.com/a/61888916/658497
Noam Manos

উত্তর:


149

আমি মনে করি এটি ঠিক যা আপনি চাইছেন তা:

http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3

#!/bin/bash
#
# The Bash shell script executes a command with a time-out.
# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
# is blocked, then the subsequent SIGKILL (9) terminates it.
#
# Based on the Bash documentation example.

# Hello Chet,
# please find attached a "little easier"  :-)  to comprehend
# time-out example.  If you find it suitable, feel free to include
# anywhere: the very same logic as in the original examples/scripts, a
# little more transparent implementation to my taste.
#
# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>

scriptName="${0##*/}"

declare -i DEFAULT_TIMEOUT=9
declare -i DEFAULT_INTERVAL=1
declare -i DEFAULT_DELAY=1

# Timeout.
declare -i timeout=DEFAULT_TIMEOUT
# Interval between checks if the process is still alive.
declare -i interval=DEFAULT_INTERVAL
# Delay between posting the SIGTERM signal and destroying the process by SIGKILL.
declare -i delay=DEFAULT_DELAY

function printUsage() {
    cat <<EOF

Synopsis
    $scriptName [-t timeout] [-i interval] [-d delay] command
    Execute a command with a time-out.
    Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM
    signal is blocked, then the subsequent SIGKILL (9) terminates it.

    -t timeout
        Number of seconds to wait for command completion.
        Default value: $DEFAULT_TIMEOUT seconds.

    -i interval
        Interval between checks if the process is still alive.
        Positive integer, default value: $DEFAULT_INTERVAL seconds.

    -d delay
        Delay between posting the SIGTERM signal and destroying the
        process by SIGKILL. Default value: $DEFAULT_DELAY seconds.

As of today, Bash does not support floating point arithmetic (sleep does),
therefore all delay/time values must be integers.
EOF
}

# Options.
while getopts ":t:i:d:" option; do
    case "$option" in
        t) timeout=$OPTARG ;;
        i) interval=$OPTARG ;;
        d) delay=$OPTARG ;;
        *) printUsage; exit 1 ;;
    esac
done
shift $((OPTIND - 1))

# $# should be at least 1 (the command to execute), however it may be strictly
# greater than 1 if the command itself has options.
if (($# == 0 || interval <= 0)); then
    printUsage
    exit 1
fi

# kill -0 pid   Exit code indicates if a signal may be sent to $pid process.
(
    ((t = timeout))

    while ((t > 0)); do
        sleep $interval
        kill -0 $$ || exit 0
        ((t -= interval))
    done

    # Be nice, post SIGTERM first.
    # The 'exit 0' below will be executed if any preceeding command fails.
    kill -s SIGTERM $$ && kill -0 $$ || exit 0
    sleep $delay
    kill -s SIGKILL $$
) 2> /dev/null &

exec "$@"

ব্যাকগ্রাউন্ড অংশের জন্য using ব্যবহার করে এটি একটি তীব্র কৌশল। এবং দুর্দান্ত যে এটি একটি ঝুলন্ত tlrbsf অবিলম্বে হত্যা করবে। তবে ওহ, আপনাকে একটি ভোটগ্রহণের ব্যবধান বেছে নিতে হবে। এবং যদি আপনি পোলিংটিকে খুব কম সেট করেন তবে এটি সিপিইউ স্থির সংকেত সহ খাবে, এতে tlrbsf আরও দীর্ঘতর হবে!
সিস্টেম PAUSE

7
আপনার ভোটদানের ব্যবধান চয়ন করতে হবে না, এটির 1 ডিফল্ট রয়েছে, এটি বেশ ভাল। এবং চেকিং খুব সাশ্রয়ী, ওভারহেড নগদ নয়। আমি সন্দেহ করি যে tlrbsf লক্ষণীয়ভাবে দীর্ঘতর হবে run আমি 30 টি ঘুমের সাথে পরীক্ষা করেছি এবং এটি ব্যবহার এবং না ব্যবহারের মধ্যে 0.000ms পার্থক্য পেয়েছি।
জুলিয়ানো

6
ঠিক আছে, আমি এখন এটি দেখতে। আপনি যদি ভোটের ব্যবধান == সময়সীমা নির্ধারণ করেন তবে এটি আমার সঠিক প্রয়োজনীয়তা পূরণ করে। পাইপলাইনগুলিতেও কাজ করে, পুরোপুরি ব্যাকগ্রাউন্ডের সাথে কাজ করে, একাধিক ঘটনা এবং অন্যান্য কাজ চলমানগুলির সাথে কাজ করে। মিষ্টি, ধন্যবাদ!
সিস্টেম PAUSE

একটি সংকেত পাঠানো সাব-শেলটিকে হত্যা করে, তাই আমি ভেবেছিলাম যে সমস্ত কিল কমান্ডকে এক লাইনে আস্তরণগুলি তাদের সংরক্ষণ করবে। অপ্রত্যাশিত ত্রুটিগুলি প্রদর্শন করতে আমি স্ট্ডার আউটপুট সক্ষম করেছিলাম। stackoverflow.com/questions/687948/...
পাঁকাল ghEEz

1
@ জুলিয়ানো সময়সীমা হ্যান্ডল করার একটি দুর্দান্ত উপায়, খুব দরকারী। আমি অবাক হই যে প্রক্রিয়াটির সময়সীমা শেষ হওয়ার পরে নিহত হওয়ার পরে যদি এমন কোনও উপায় থাকে যেখানে আমরা স্ক্রিপ্টের এক্সটিকোড 143 পেতে পারি? আমি কিল কমান্ডের ঠিক পরে "প্রস্থান 143" যুক্ত করার চেষ্টা করেছি, তবে আমি সবসময় কলার স্ক্রিপ্টে প্রস্থান কোড 0 পাই।
সালমান এ। কাগজি

528

আপনি সম্ভবত timeoutকোর্টিলগুলিতে কমান্ডটি সন্ধান করছেন। যেহেতু এটি কোর্টিলগুলির একটি অংশ, এটি প্রযুক্তিগতভাবে একটি সি দ্রবণ তবে এটি এখনও কোর্টিলস। info timeoutআরো বিস্তারিত জানার জন্য. এখানে একটি উদাহরণ:

timeout 5 /path/to/slow/command with options

21
ম্যাক এ আপনি ম্যাকপোর্ট বা হোমব্রুয়ের মাধ্যমে ইনস্টল করতে পারেন।
ইভান জেড সিউ

23
ওএস এক্স-এ হোমব্রিউয়ের মাধ্যমে ইনস্টল করা হলে কমান্ডটি হয়ে যায়gtimeout
এথিক্যালহ্যাক

5
... 2003 এর আগে আপনি কী ওএস ব্যবহার করছেন যাতে কোরিউটিল রয়েছে?
কিথ

5
@ কিথ: সেন্টোস ৫.১০, উদাহরণস্বরূপ :-(
পরবর্তী বিজ্ঞপ্তি না হওয়া পর্যন্ত

9
স্পষ্ট করার জন্য, ওএসএক্স / ম্যাকের জন্য আপনার যে হোমব্রেউ কমান্ডটি দরকার তা হ'ল brew install coreutilsএবং তারপরে আপনি এটি ব্যবহার করতে পারেন gtimeout
ওহাদ স্নাইডার

37

এই সমাধানটি ব্যাশ মনিটরের মোড নির্বিশেষে কাজ করে। আপনি আপনার_কম্যান্ডটি শেষ করতে সঠিক সংকেতটি ব্যবহার করতে পারেন

#!/bin/sh
( your_command ) & pid=$!
( sleep $TIMEOUT && kill -HUP $pid ) 2>/dev/null & watcher=$!
wait $pid 2>/dev/null && pkill -HUP -P $watcher

প্রদত্ত সময়সীমার পরে পর্যবেক্ষক আপনার_কম্যান্ডকে হত্যা করে; স্ক্রিপ্টটি ধীর কাজটির জন্য অপেক্ষা করে এবং পর্যবেক্ষককে সমাপ্ত করে। নোটটি যে waitকোনও প্রক্রিয়াগুলির সাথে কাজ করে না যা পৃথক শেলের শিশু।

উদাহরণ:

  • আপনার_কম্যান্ডটি 2 সেকেন্ডেরও বেশি সময় ধরে চালিত হয় এবং সমাপ্ত হয়

আপনার_কম্যান্ড বাধা পেয়েছে

( sleep 20 ) & pid=$!
( sleep 2 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
    echo "your_command finished"
    pkill -HUP -P $watcher
    wait $watcher
else
    echo "your_command interrupted"
fi
  • আপনার_কামন্ডটি সময়সীমা শেষ হওয়ার আগে (20 সেকেন্ড)

আপনার_কমন্ডল শেষ হয়েছে

( sleep 2 ) & pid=$!
( sleep 20 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
    echo "your_command finished"
    pkill -HUP -P $watcher
    wait $watcher
else
    echo "your_command interrupted"
fi

1
waitপ্রক্রিয়াটির অপেক্ষার স্থিতি এটি প্রত্যাশায় ফিরে আসে। সুতরাং যদি আপনার আদেশটি নির্ধারিত সময়ের মধ্যে প্রস্থান করে তবে একটি শূন্য-বহির্গমন স্থিতি দিয়ে থাকে তবে এখানে যুক্তিটি সময়সীমার সাথে আচরণ করবে, যেমন মুদ্রণ your_command interrupted। পরিবর্তে আপনি একটি ছাড়াই এটি করতে পারেন এবং তারপরে পিডটি এখনও আছে কিনা তা পরীক্ষা করে দেখতে পারেন , যদি তা হয় তবে আপনি জানেন যে আপনার সময়সীমা শেষ হয়নি। waitif$watcher
জর্জ হকিন্স

আমি কেন বুঝতে পারি না এটি কেন killএক ক্ষেত্রে ব্যবহার করে তবে অন্য ক্ষেত্রে pkillpkillএই কাজটি সঠিকভাবে করার জন্য আমার উভয়ের জন্য ব্যবহার করা দরকার । আমি প্রত্যাশা করব যে আপনি যদি একটি কমান্ড মুড়ে ফেলে থাকেন ()তবে আপনাকে pkillএটি হত্যা করতে হবে। তবে সম্ভবত এটি আলাদাভাবে কাজ করে যদি এর ভিতরে কেবল একটি কমান্ড থাকে ()
নভেম্বর


22

এই নাও:

timeout --signal=SIGINT 10 /path/to/slow command with options

আপনি পরিবর্তন করতে পারেন SIGINTএবং 10আপনার ইচ্ছামতো;)


3
"টাইমআউট" হ'ল (কমপক্ষে) রেডহাট, সেন্টোস, সুস এবং উবুন্টুতে কোর্টিলিজ প্যাকেজের অংশ , সুতরাং আপনার যদি এটি না থাকে তবে এটি ইনস্টল করতে হবে।
আকোম

এটা সত্যিই সহায়ক !!!!!! আপনি কি জানেন যে কেন ইয়িংটেডের "সময়সীমা 5 / পথ / টু / স্লো / কমান্ড" বিকল্পগুলি মাঝে মাঝে কাজ করে না?
ডেকুলা

দুর্ভাগ্যক্রমে coreutilsএটি ফ্রিবিএসডি- র প্যাকেজে নেই।
পল বিসেক্স

18

আপনি এটি সম্পূর্ণরূপে bash 4.3এবং এর সাথে করতে পারেন :

_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; r=$?; kill -9 `jobs -p`; exit $r; ) }
  • উদাহরণ: _timeout 5 longrunning_command args
  • উদাহরণ: { _timeout 5 producer || echo KABOOM $?; } | consumer
  • উদাহরণ: producer | { _timeout 5 consumer1; consumer2; }
  • উদাহরণ: { while date; do sleep .3; done; } | _timeout 5 cat | less

  • 4.4 এর জন্য বাশ দরকার wait -n

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

আপনার যদি রিটার্ন কোডের প্রয়োজন না হয় তবে এটি আরও সহজ করা যেতে পারে:

_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; kill -9 `jobs -p`; ) }

মন্তব্য:

  • স্ট্রিক্টলি আপনি প্রয়োজন নেই ভাষী ;মধ্যে ; )অবশ্য এটা আরো সামঞ্জস্যপূর্ণ জিনিস তোলে ; }-case। এবং set +bসম্ভবত দূরে রাখা যেতে পারে, কিন্তু দুঃখিত চেয়ে ভাল নিরাপদ।

  • --forground(সম্ভবত) ব্যতীত আপনি সমস্ত বৈকল্পিক timeoutসমর্থন বাস্তবায়ন করতে পারেন । --preserve-statusযদিও কিছুটা কঠিন। এটি পাঠকের অনুশীলন হিসাবে ছেড়ে গেছে;)

এই রেসিপিটি শেলটিতে "প্রাকৃতিকভাবে" ব্যবহার করা যায় (যতটা প্রাকৃতিক flock fd):

(
set +b
sleep 20 &
{
YOUR SHELL CODE HERE
} &
wait -n
kill `jobs -p`
)

তবে উপরে বর্ণিত হিসাবে আপনি প্রাকৃতিকভাবে এনকোমেলিং শেলটিতে পরিবেশের পরিবর্তনগুলি পুনরায় রফতানি করতে পারবেন না।

সম্পাদনা:

বাস্তব বিশ্বের উদাহরণ: সময় __git_ps1খুব বেশি সময় নেয় (ধীর এসএসএফএস-লিংকের মতো জিনিসের জন্য):

eval "__orig$(declare -f __git_ps1)" && __git_ps1() { ( git() { _timeout 0.3 /usr/bin/git "$@"; }; _timeout 0.3 __orig__git_ps1 "$@"; ) }

সম্পাদনা 2: বাগফিক্স। আমি লক্ষ্য করেছি যে exit 137এটি প্রয়োজন নেই এবং _timeoutএকই সাথে অবিশ্বাস্য করে তোলে ।

সম্পাদনা 3: gitডাই-হার্ড, সুতরাং সন্তুষ্টিজনকভাবে কাজ করার জন্য এটি ডাবল ট্রিকের প্রয়োজন।

সম্পাদনা 4: বাস্তব বিশ্বের জিআইটি উদাহরণের জন্য _প্রথমটিতে একটি ভুলে গেছেন _timeout


1
বাশ 4 শিলা। এটাই সব।
সিস্টেম PAUSE

1
এটির জন্য আসলে 4.3 বা আরও বাশ প্রয়োজন। cc. The 'wait' builtin has a new '-n' option to wait for the next child to change status. থেকে: tiswww.case.edu/php/chet/bash/NEWS
বেন রেজার

17

আমি "টাইমলিমিট" পছন্দ করি, এতে কমপক্ষে ডেবিয়ানে প্যাকেজ রয়েছে।

http://devel.ringlet.net/sysutils/timelimit/

এটি কোর্টিলগুলি "টাইমআউট" এর চেয়ে কিছুটা সুন্দর কারণ প্রক্রিয়াটি হত্যার সময় এটি কিছু মুদ্রণ করে এবং এটি ডিফল্টরূপে কিছু সময়ের পরে সিগিলও প্রেরণ করে।


এটি বেশ ভালভাবে কাজ করছে বলে মনে হচ্ছে না: / time সময়সীম -T2 ঘুম 10 আসল 0m10.003s ব্যবহারকারী 0m0.000s sys 0m0.000s
হিটওয়েন

3
-T2 না -T2 ব্যবহার করুন। বিগ-টি হ'ল সিগন্যাল পাঠানো থেকে সিগ্কিল পাঠানো অবধি।
ম্যাক্সি

1
আমি এই টাইমলিমিট ১.৮ টি যুক্ত করতে চাই যাতে কাঁটাচামচ ( timelimit -t1 ./a_forking_progদুটি প্রক্রিয়ার মধ্যে কেবল একটিকে মেরে ফেলতে পারে) ভাল কাজ করতে পারে না , তবে সময়সীমা কাজ করে।
জেরেমি কোচয়

প্রক্রিয়াটি হত্যার সময় আপনি যদি কিছু মুদ্রণের সময়সীমা চান তবে কেবল "-v" পতাকাটি ব্যবহার করুন।

10

slowcommand1 সেকেন্ড পরে সময়সীমা শেষ :

timeout 1 slowcommand || echo "I failed, perhaps due to time out"

কমান্ডটি তার নিজস্ব কারণে শেষ হয়ে গেছে বা ব্যর্থ হয়েছে তা নির্ধারণের জন্য, স্থিতি কোডটি 124 কিনা তা পরীক্ষা করুন:

# ping for 3 seconds, but timeout after only 1 second
timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process Timed Out!'
else
echo 'Process did not timeout. Something else went wrong.'
fi
exit $EXIT_STATUS

দ্রষ্টব্য যে যখন প্রস্থান স্থিতি 124 হবে তখন আপনি জানেন না যে এটি আপনার timeoutকমান্ডের কারণে সময়সীমা বেঁধেছে কিনা , অথবা কমান্ডটি নিজেই কোনও অভ্যন্তরীণ সময়সীমা যুক্ত হওয়ার কারণে নিজেই সমাপ্ত হয়েছিল এবং 124 ফিরে এসেছে whether আপনি উভয় ক্ষেত্রেই নিরাপদে ধরে নিতে পারেন can যাইহোক, যে এক ধরণের সময়সীমা ঘটেছে।


9

আরও দেখুন http://www.pixelbeat.org/scripts/timeout স্ক্রিপ্ট কার্যকারিতা যার নতুন coreutils মধ্যে একত্রিত করা হয়েছে


ঝরঝরে, সরল, TERM ব্যবহার করে না খুন করে। নিস! আমি যখন প্রাথমিকভাবে প্রশ্নটি উত্থাপন করি তখন আমি এই জাতীয় ফাঁদ / অপেক্ষা সমাধানটি অন্বেষণ করে যাচ্ছিলাম।
সিস্টেম PAUSE

সময়সীমা একটি হত্যার ক্ষেত্রে 124 প্রদান করে।
সিভ করা

8

কিন্ডা হ্যাকি, তবে এটি কাজ করে। আপনার অন্যান্য অগ্রভাগ প্রক্রিয়া থাকলে কাজ করে না (দয়া করে আমাকে এটি ঠিক করতে সহায়তা করুন!)

sleep TIMEOUT & SPID=${!}; (YOUR COMMAND HERE; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}

প্রকৃতপক্ষে, আমি মনে করি আপনি আপনার 'বোনাস' মানদণ্ড পূরণ করে এটির বিপরীতমুখী করতে পারেন:

(YOUR COMMAND HERE & SPID=${!}; (sleep TIMEOUT; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}) < asdf > fdsa

(ls -ltR / cygdrive / c / Windows & SPID = $ {!}; (ঘুম 1s; কিল $ {এসপিআইডি &) & সিপিআইডি = $ {! fg 1; কিল $ {সিপিআইডি})> fdsa
সিস্টেম

bash: fg: কোন
जॉब

@ সিস্টেম পাস, সেট-মি, আমি মনে করি।
স্ট্র্যাজার

লগইন শেলটিতে আমার জব কন্ট্রোল (সেট-এম) রয়েছে। এটি him এরHHH কনটেন্টে 'মি', তবে এটি সাব-শেলের জন্য অদৃশ্য হয়ে গেছে বলে মনে হয়। সম্ভবত একটি সাইগউইন নিদর্শন। গ্র্যাম্বল
সিস্টেমে PAUSE

স্ক্রিপ্টগুলিতে "fg" ব্যবহার করবেন না। "সহায়তা অপেক্ষা" পড়ুন।
লুুনাথ

8

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

if 
    timeout 20s COMMAND_YOU_WANT_TO_EXECUTE;
    timeout 20s AS_MANY_COMMANDS_AS_YOU_WANT;
then
    echo 'OK'; #if you want a positive response
else
    echo 'Not OK';
    AND_ALTERNATIVE_COMMANDS
fi

5

কোড স্পষ্টতা সহ সহজ স্ক্রিপ্ট। এতে সংরক্ষণ করুন /usr/local/bin/run:

#!/bin/bash

# run
# Run command with timeout $1 seconds.

# Timeout seconds
timeout_seconds="$1"
shift

# PID
pid=$$

# Start timeout
(
  sleep "$timeout_seconds"
  echo "Timed out after $timeout_seconds seconds"
  kill -- -$pid &>/dev/null
) &
timeout_pid=$!

# Run
"$@"

# Stop timeout
kill $timeout_pid &>/dev/null

একটি কমান্ড টাইম করে যা খুব দীর্ঘ চলে:

$ run 2 sleep 10
Timed out after 2 seconds
Terminated
$

সম্পূর্ণ হওয়া একটি আদেশের জন্য অবিলম্বে শেষ হয়:

$ run 10 sleep 2
$

3

programটাইমআউট (উদাহরণ 3সেকেন্ড হিসাবে) শেষ হওয়ার পরে যদি প্রোগ্রামটির নামটি (ইতিমধ্যে ধরে নেওয়া যাক ) ইতিমধ্যে আপনি জানেন তবে আমি একটি সহজ এবং কিছুটা নোংরা বিকল্প সমাধান অবদান রাখতে পারি:

(sleep 3 && killall program) & ./program

যদি আমি সিস্টেম কল সহ বেনমার্ক প্রসেসগুলি কল করি তবে এটি পুরোপুরি কার্যকর হয়।


2
এটি নাম ব্যবহার করার ক্ষেত্রে ঘটে এমন অন্যান্য প্রক্রিয়াগুলিকে হত্যা করে এবং প্রদত্ত নামের সাথে প্রক্রিয়াটির নাম পরিবর্তন করে না তবে এটি উদাহরণস্বরূপ (উদাহরণস্বরূপ argv[0], আরও হ্যাক করার জন্য অন্যান্য হ্যাকের সাথে লিখে )।
জেড

নির্দিষ্ট সময় পরে ডকার পাত্রে থামানোর চেষ্টা করার সময় আমি এই হ্যান্ডিটির একটি বৈচিত্র পেয়েছি। ডকার ক্লায়েন্ট টিআরএম / আইএনটি / কেএলএলকে এমনভাবে গ্রহণ করবে বলে মনে হয় নি যা পূর্বের অংশে চালিত পাত্রে আসলে থামবে। সুতরাং ধারকটিকে একটি নাম দেওয়া এবং দুর্দান্তভাবে ব্যবহার করা (sleep 3 && docker stop <container>) &। ধন্যবাদ!
মাদুর শেফার

হ্যাঁ এটি ময়লা এবং সীমাবদ্ধ, তবে এর মতো উন্নতি করা যেতে পারে: { sleep 5 && kill -9 $(ps -fe | grep "program" | grep $$ | tr -s " " | cut -d" " -f2); } & SLEEPPID=$!; bash -c "program" && kill -9 $SLEEPPID"এইভাবে, এটি কেবলমাত্র বর্তমান শেলটিতে কাজগুলি মেরে ফেলবে।
টন

2

এছাড়াও আছে cratimeoutমার্টিন Cracauer (ইউনিক্স এবং Linux সিস্টেমের জন্য সি লিখিত) দ্বারা।

# cf. http://www.cons.org/cracauer/software.html
# usage: cratimeout timeout_in_msec cmd args
cratimeout 5000 sleep 1
cratimeout 5000 sleep 600
cratimeout 5000 tail -f /dev/null
cratimeout 5000 sh -c 'while sleep 1; do date; done'

"বিশেষত, এটি সংকেত আচরণ সংরক্ষণ করে।" অপশনটি পেয়ে ভালো লাগল!
সিস্টেম PAUSE

1

ওএস এক্স এখনও ব্যাশ 4 ব্যবহার করে না, এটিতে / ইউএসআর / বিন / টাইমআউটও নেই, সুতরাং এখানে একটি ফাংশন রয়েছে যা ওএস এক্স-এ হোম-ব্রিউ বা ম্যাকপোর্টগুলি / ইউএসআর / বিন / টাইমআউট সমান (টিনোর উপর ভিত্তি করে) সমান উত্তর). প্যারামিটারের বৈধতা, সহায়তা, ব্যবহার এবং অন্যান্য সংকেতের জন্য সমর্থন পাঠকের জন্য অনুশীলন।

# implement /usr/bin/timeout only if it doesn't exist
[ -n "$(type -p timeout 2>&1)" ] || function timeout { (
    set -m +b
    sleep "$1" &
    SPID=${!}
    ("${@:2}"; RETVAL=$?; kill ${SPID}; exit $RETVAL) &
    CPID=${!}
    wait %1
    SLEEPRETVAL=$?
    if [ $SLEEPRETVAL -eq 0 ] && kill ${CPID} >/dev/null 2>&1 ; then
      RETVAL=124
      # When you need to make sure it dies
      #(sleep 1; kill -9 ${CPID} >/dev/null 2>&1)&
      wait %2
    else
      wait %2
      RETVAL=$?
    fi
    return $RETVAL
) }

0

99% ক্ষেত্রে উত্তরটি কোনও সময়সীমা যুক্তি বাস্তবায়নের নয়। সময়সীমা যুক্তি প্রায় কোনও পরিস্থিতিতে একটি লাল সতর্কতার চিহ্ন যে অন্য কিছু ভুল এবং পরিবর্তে এটি ঠিক করা উচিত ।

আপনার প্রক্রিয়াটি কখনও কখনও n সেকেন্ড পরে ঝুলন্ত বা ব্রেক হয়ে যায়? তারপরে কেন এটি সন্ধান করুন এবং পরিবর্তে এটি ঠিক করুন।

অন্যদিকে স্ট্র্যাজারের সমাধানটি সঠিকভাবে করার জন্য আপনার এফজি 1 এর পরিবর্তে ওয়েট "$ এসপিআইডি" ব্যবহার করা উচিত, যেহেতু স্ক্রিপ্টগুলিতে আপনার কাজের নিয়ন্ত্রণ নেই (এবং এটি চালু করার চেষ্টাটি বোকামি)। তদুপরি, এফজি 1 এই বিষয়টির উপর নির্ভর করে যে আপনি স্ক্রিপ্টে অন্য কোনও কাজ শুরু করেন নি যা করা খারাপ ধারণা।


4
100% উত্স অ্যাক্সেসের সাথে (এবং বেশিরভাগ হার্ডওয়্যার যেমন নেটওয়ার্ক স্যুইচগুলি) অ্যাক্সেসের সাথে আমি সম্মত হব যে একটি সময়সীমার চেয়ে সম্ভবত আরও ভাল সমাধান রয়েছে। কিন্তু যখন একটি 'tlrbsf' ক্লোজ-সোর্স হয় কেবল বাইনারি, কখনও কখনও আপনাকে সেই সীমাবদ্ধতার চারপাশে কাজ করতে হয়।
সিস্টেম PAUSE

: - @lhunath, "স্ক্রিপ্ট আপনি কাজের নিয়ন্ত্রণ না থাকে (এবং এটি চালু করার চেষ্টা মূঢ়) এ" তুমি এখানেই নির্মল stackoverflow.com/questions/690266/...
সিস্টেম বিরাম

@system বিরাম: উত্তর stackoverflow.com/questions/690266/... সঠিক, আমিও এটিতে মন্তব্য।
লুুনাথ

29
লুনাথ, আপনি যা বলছেন তা বোধগম্য নয়। এমন অনেকগুলি কেস রয়েছে যেখানে সময় নির্ধারণ করা একটি ভাল বিকল্প, যেমন আপনাকে যে কোনও সময় নেটওয়ার্কের বাইরে যেতে হবে।
নাট মারে

একটি ব্যতিক্রম: আপনি ইতিমধ্যে চলমান সফ্টওয়্যারটির টাইমআউট সমস্যা নেই কিনা তা পরীক্ষা করতে আপনি পরীক্ষা স্ক্রিপ্ট লিখছেন ।
পিটারহ - মনিকা

0

শেল প্রসঙ্গে সংরক্ষণ করতে এবং টাইমআউটগুলিকে অনুমতি দেওয়ার জন্য আমাকে একটি সমস্যা হাজির করা হয়েছিল, এটির সাথে একমাত্র সমস্যা হ'ল সময়সীমার স্ক্রিপ্ট সম্পাদন বন্ধ হবে - তবে আমাকে যে প্রয়োজনীয়তা উপস্থাপন করা হয়েছিল তা ঠিক আছে:

#!/usr/bin/env bash

safe_kill()
{
  ps aux | grep -v grep | grep $1 >/dev/null && kill ${2:-} $1
}

my_timeout()
{
  typeset _my_timeout _waiter_pid _return
  _my_timeout=$1
  echo "Timeout($_my_timeout) running: $*"
  shift
  (
    trap "return 0" USR1
    sleep $_my_timeout
    echo "Timeout($_my_timeout) reached for: $*"
    safe_kill $$
  ) &
  _waiter_pid=$!
  "$@" || _return=$?
  safe_kill $_waiter_pid -USR1
  echo "Timeout($_my_timeout) ran: $*"
  return ${_return:-0}
}

my_timeout 3 cd scripts
my_timeout 3 pwd
my_timeout 3 true  && echo true || echo false
my_timeout 3 false && echo true || echo false
my_timeout 3 sleep 10
my_timeout 3 pwd

ফলাফলগুলি সহ:

Timeout(3) running: 3 cd scripts
Timeout(3) ran: cd scripts
Timeout(3) running: 3 pwd
/home/mpapis/projects/rvm/rvm/scripts
Timeout(3) ran: pwd
Timeout(3) running: 3 true
Timeout(3) ran: true
true
Timeout(3) running: 3 false
Timeout(3) ran: false
false
Timeout(3) running: 3 sleep 10
Timeout(3) reached for: sleep 10
Terminated

অবশ্যই আমি ধরে নিয়েছি সেখানে একটি ডির ডাকা হয়েছিল scripts


0
#! /bin/bash
timeout=10
interval=1
delay=3
(
    ((t = timeout)) || :

    while ((t > 0)); do
        echo "$t"
        sleep $interval
        # Check if the process still exists.
        kill -0 $$ 2> /dev/null || exit 0
        ((t -= interval)) || :
    done

    # Be nice, post SIGTERM first.
    { echo SIGTERM to $$ ; kill -s TERM $$ ; sleep $delay ; kill -0 $$ 2> /dev/null && { echo SIGKILL to $$ ; kill -s KILL $$ ; } ; }
) &

exec "$@"

@ টিনো দুঃখিত আমি কেন প্রক্রিয়া সমাপ্তির লাইনটি পরিবর্তন করেছি এবং কেন এটি ভাগ করে নেওয়া গুরুত্বপূর্ণ বলে আমি ভুলে গেছি important খুব খারাপ আমি এটি লিখিনি। সম্ভবত, আমি খুঁজে পেয়েছি যে কিল-এস টিআরএম এর সাফল্য যাচাই করার আগে আমাকে বিরতি দেওয়া দরকার ছিল। ২০০৮ সালের কুক বইয়ের লিপিটি SIGTERM প্রেরণের সাথে সাথেই প্রক্রিয়াটির অবস্থা পরীক্ষা করে দেখে মনে হচ্ছে যে সম্ভবত মারা যাওয়া প্রক্রিয়ায় সিগকলকে প্রেরণের চেষ্টা করার সময় ত্রুটি ঘটেছে।
ইয়েল ghEEz

0

আমার সমস্যাটি কিছুটা আলাদা ছিল: আমি দূরবর্তী মেশিনে এসএসএসের মাধ্যমে একটি কমান্ড শুরু করি এবং কমান্ডটি স্থগিত হলে শেল এবং শিশুদের হত্যা করতে চাই।

আমি এখন নিম্নলিখিত ব্যবহার:

ssh server '( sleep 60 && kill -9 0 ) 2>/dev/null & my_command; RC=$? ; sleep 1 ; pkill -P $! ; exit $RC'

সাফল্যের ক্ষেত্রে কমান্ডের সময়সীমা বা রিটার্নকোড থাকার সময় এই কমান্ডটি 255 প্রদান করে

দয়া করে মনে রাখবেন যে ssh সেশন থেকে হত্যা প্রক্রিয়াগুলি ইন্টারেক্টিভ শেল থেকে পৃথকভাবে পরিচালিত হয়। আপনি সিউডো টার্মিনাল বরাদ্দ করতে ssh করতে -t বিকল্পটিও ব্যবহার করতে পারেন, সুতরাং এটি একটি ইন্টারেক্টিভ শেলের মতো কাজ করে


0

এখানে এমন একটি সংস্করণ যা কোনও শিশু প্রক্রিয়া তৈরির উপর নির্ভর করে না - আমার একটি স্ট্যান্ডলোন স্ক্রিপ্টের প্রয়োজন ছিল যা এই কার্যকারিতাটি এম্বেড করেছিল। এটি একটি ভগ্নাংশের পোল ব্যবধানও করে, যাতে আপনি আরও দ্রুত পোল করতে পারেন। সময়সীমাটি অগ্রাধিকার দেওয়া হত - তবে আমি পুরানো সার্ভারে আটকে আছি

# wait_on_command <timeout> <poll interval> command
wait_on_command()
{
    local timeout=$1; shift
    local interval=$1; shift
    $* &
    local child=$!

    loops=$(bc <<< "($timeout * (1 / $interval)) + 0.5" | sed 's/\..*//g')
    ((t = loops))
    while ((t > 0)); do
        sleep $interval
        kill -0 $child &>/dev/null || return
        ((t -= 1))
    done

    kill $child &>/dev/null || kill -0 $child &>/dev/null || return
    sleep $interval
    kill -9 $child &>/dev/null
    echo Timed out
}

slow_command()
{
    sleep 2
    echo Completed normally
}

# wait 1 sec in 0.1 sec increments
wait_on_command 1 0.1 slow_command

# or call an external command
wait_on_command 1 0.1 sleep 10

-1

খুব সরল পদ্ধতি:

# command & sleep 5; pkill -9 -x -f "command"

সঙ্গে pkill (বিকল্প -f ) আপনি আর্গুমেন্ট সহ আপনার নির্দিষ্ট কমান্ড হত্যা বা পুরাতন প্রক্রিয়া হত্যা এড়াতে -n নির্দিষ্ট করতে পারেন।


আপনি বুঝতে পারেন যে এটি তার পোস্টে মূলত অপরিবর্তিত রয়েছে এবং তিনি কী চান তা তিনি চান না, তাই না? কারণ এটি সর্বদা পুরো ঘুমের বিলম্বের জন্য অপেক্ষা করে।
এটান রেইজনার

-1

@ লুপের উত্তরে বিল্ডিং ...

আপনি যদি কোনও প্রক্রিয়া শেষ করতে চান এবং কিল জব / পিড আউটপুট নিরব করতে চান তবে চালান:

( (sleep 1 && killall program 2>/dev/null) &) && program --version 

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


-3

আমার একটি ক্রোন জব রয়েছে যা একটি পিএইচপি স্ক্রিপ্টকে কল করে এবং কিছু সময় এটি পিএইচপি স্ক্রিপ্টে আটকে যায়। এই সমাধানটি আমার পক্ষে নিখুঁত ছিল।

আমি ব্যবহার করি:

scripttimeout -t 60 /script.php

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