ঘুম কমান্ড ব্যতীত ব্যাশে অপেক্ষা করতে ব্যস্ত হওয়া এড়ানো


19

আমি জানি আমি কাজ করে বাশে সত্য হয়ে ওঠার শর্তের জন্য অপেক্ষা করতে পারি:

while true; do
  test_condition && break
  sleep 1
done

তবে এটি প্রতিটি পুনরাবৃত্তিতে (ঘুম) 1 টি উপ-প্রক্রিয়া তৈরি করে। আমি এগুলি করে এড়াতে পারতাম:

while true; do
  test_condition && break
done

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

my_tmp_dir=$(mktemp -d --tmpdir=/tmp)    # Create a unique tmp dir for the fifo.
mkfifo $my_tmp_dir/fifo                  # Create an empty fifo for sleep by read.
exec 3<> $my_tmp_dir/fifo                # Open the fifo for reading and writing.

while true; do
  test_condition && break
  read -t 1 -u 3 var                     # Same as sleep 1, but without sub-process.
done

exec 3<&-                                # Closing the fifo.
rm $my_tmp_dir/fifo; rmdir $my_tmp_dir   # Cleanup, could be done in a trap.

দ্রষ্টব্য: সাধারণ ক্ষেত্রে, আমি কেবল read -t 1 varফিফো ছাড়া ব্যবহার করতে পারি না , কারণ এটি স্টিডিন গ্রাস করবে, এবং স্টিডিন টার্মিনাল বা পাইপ না হলে কাজ করবে না।

আমি কি উপ-প্রক্রিয়াগুলি এবং আরও মার্জিত উপায়ে অপেক্ষা করতে ব্যস্ত থাকতে পারি?


1
trueএটি একটি অন্তর্নির্মিত এবং ব্যাশে একটি উপ-প্রক্রিয়া তৈরি করে না। ব্যস্ত অপেক্ষা সবসময় খারাপ হবে।
jordanm

@ জোড়ানম: আপনি ঠিক বলেছেন true, প্রশ্ন আপডেট হয়েছে।
jfg956

ফিফো ছাড়া হয় না কেন? সহজভাবে read -t 1 var
অট--

@ নীচে: আপনি ঠিক বলেছেন, তবে এটি স্টিডিন গ্রাস করবে। এছাড়াও, স্টিডিন যদি টার্মিনাল বা পাইপ না হয় তবে এটি কাজ করবে না।
jfg956

যদি রক্ষণাবেক্ষণযোগ্যতা একটি সমস্যা হয় তবে আমি sleepপ্রথম উদাহরণের মতো দৃ strongly়তার সাথে পরামর্শ দেওয়ার পরামর্শ দেব । দ্বিতীয়টি, এটি কাজ করতে পারে, তবে ভবিষ্যতে কারও পক্ষে সামঞ্জস্য করা সহজ হবে না। সরল কোডেও নিরাপদ থাকার বড় সম্ভাবনা রয়েছে
কুসালানন্দ

উত্তর:


17

bash(কমপক্ষে v2) এর নতুন সংস্করণগুলিতে বিল্টিনগুলি enable -f filename commandnameরানটাইমের সময় (এর মাধ্যমে ) লোড হতে পারে । এ জাতীয় প্রচুর লোডযোগ্য বিল্টিনগুলি বাশ উত্সের সাথে বিতরণ করা হয় এবং সেগুলির মধ্যে একটি sleep। উপলভ্যতা অবশ্যই ওএস থেকে ওএস (এমনকি মেশিন থেকে মেশিন) থেকেও আলাদা হতে পারে। উদাহরণস্বরূপ, ওপেনসুসে, এই বিল্টিনগুলি প্যাকেজের মাধ্যমে বিতরণ করা হয় bash-loadables

সম্পাদনা করুন: প্যাকেজের নাম ঠিক করুন, সর্বনিম্ন বাশ সংস্করণ যুক্ত করুন।


বাহ, এটি আমি যা খুঁজছি এবং আমি স্পষ্টভাবে লোডযোগ্য বিল্টিন সম্পর্কে কিছু শিখতে পারি: +1। আমি এটি চেষ্টা করব, এবং এখনও এটি সেরা উত্তর।
jfg956

1
এটি কাজ করে! ডিবিয়ান-এ, প্যাকেজটি ব্যাশ-বিল্টিন রয়েছে ins এটিতে কেবল উত্স অন্তর্ভুক্ত রয়েছে এবং মেকফিল অবশ্যই সম্পাদিত হওয়া উচিত তবে আমি sleepবিল্টিন হিসাবে ইনস্টল করতে সক্ষম হয়েছি । ধন্যবাদ।
jfg956

9

অভ্যন্তরীণ লুপে প্রচুর সাব-প্রসেসগুলি তৈরি করা একটি খারাপ জিনিস। sleepপ্রতি সেকেন্ডে একটি প্রক্রিয়া তৈরি করা ঠিক আছে। এতে কোনও ভুল নেই

while ! test_condition; do
  sleep 1
done

আপনি যদি সত্যই বাহ্যিক প্রক্রিয়া এড়াতে চান তবে আপনার ফিফোটি খোলার দরকার নেই।

my_tmpdir=$(mktemp -d)
trap 'rm -rf "$my_tmpdir"' 0
mkfifo "$my_tmpdir/f"

while ! test_condition; do
  read -t 1 <>"$my_tmpdir/f"
done

আপনি প্রতি সেকেন্ডে চিনাবাদাম হওয়ার প্রক্রিয়া সম্পর্কে ঠিক বলেছেন (তবে আমার প্রশ্নটি এটি অপসারণের উপায় অনুসন্ধান করার বিষয়ে ছিল)। সংক্ষিপ্ত সংস্করণ সম্পর্কে, এটি আমার চেয়ে সুন্দর, সুতরাং +1 (তবে এটি mkdirযেভাবে করা হচ্ছে আমি তা সরিয়েছি mktemp(যদি না হয় তবে এটি একটি জাতি শর্ত))। while ! test_condition;আমার প্রাথমিক সমাধানের চেয়ে ভাল এটি সম্পর্কেও সত্য ।
jfg956

7

আমার সম্প্রতি এটি করা দরকার ছিল। আমি নিম্নলিখিত ফাংশন নিয়ে এসেছি যা কোনও বাহ্যিক প্রোগ্রাম না ডেকে বাশকে চিরকাল ঘুমাতে দেয়:

snore()
{
    local IFS
    [[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
    {
        # workaround for MacOS and similar systems
        local fifo
        fifo=$(mktemp -u)
        mkfifo -m 700 "$fifo"
        exec {_snore_fd}<>"$fifo"
        rm "$fifo"
    }
    read ${1:+-t "$1"} -u $_snore_fd || :
}

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

এটিকে ঠিক / বিন / ঘুমের মতো বলা যেতে পারে এবং এটি অনুরোধকৃত সময়ের জন্য ঘুমাবে। প্যারামিটার ছাড়াই কল করা, এটি চিরতরে স্তব্ধ হয়ে থাকবে।

snore 0.1  # sleeps for 0.1 seconds
snore 10   # sleeps for 10 seconds
snore      # sleeps forever

আমার ব্লগে এখানে অতিরিক্ত বিবরণ সহ একটি লিখনআপ রয়েছে


1
দুর্দান্ত ব্লগ এন্ট্রি। যাইহোক, পুরো 10 সেকেন্ডের জন্য অপেক্ষা করার read -t 10 < <(:)পরে কেন তত্ক্ষণাত্ ফিরে আসে তার ব্যাখ্যা খুঁজতে আমি সেখানে গিয়েছিলাম read -t 10 <> <(:), কিন্তু আমি এখনও এটি পাই না।
আমির

ইন read -t 10 <> <(:)কী <>জন্য দাঁড়াবেন?
কোডমেডিক

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

3

ইন ksh93বা mksh, sleepএকটি শেল builtin, তাই একটি বিকল্প পরিবর্তে ঐ শাঁস ব্যবহার করতে হতে পারে হয় bash

zshএছাড়াও একটি zselectবিল্টিন রয়েছে (এতে বোঝাই zmodload zsh/zselect) যা প্রদত্ত সংখ্যক সেকেন্ডের সেকেন্ডের জন্য ঘুমাতে পারে zselect -t <n>


2

ব্যবহারকারী যোই যেমন বলেছিলেন, আপনার স্ক্রিপ্টে যদি স্টিডিনটি খোলা থাকে তবে 1 ঘুমের পরিবর্তে আপনি কেবল ব্যবহার করতে পারেন:

read -t 1 3<&- 3<&0 <&3

বাশ সংস্করণ 4.1 এবং আরও নতুনতে আপনি ভাসা নম্বর ব্যবহার করতে পারেন, যেমন read -t 0.3 ...

যদি কোনও স্ক্রিপ্টে স্টিডিন বন্ধ থাকে (স্ক্রিপ্ট বলা হয় my_script.sh < /dev/null &), তবে আপনার আর একটি খোলা বর্ণনাকারী ব্যবহার করা দরকার, যা পাঠানো কার্যকর হলে আউটপুট উত্পাদন করে না , যেমন। স্টাডাউট :

read -t 1 <&1 3<&- 3<&0 <&3

যদি কোনও স্ক্রিপ্টে সমস্ত বর্ণনাকারী বন্ধ থাকে ( স্টিডিন , স্ট্ডআউট , স্ট্ডার ) (উদাহরণস্বরূপ কারণ এটি ডেমন হিসাবে পরিচিত), তবে আপনার কোনও উপস্থিত ফাইল খুঁজে পাওয়া দরকার যা আউটপুট তৈরি করে না:

read -t 1 </dev/tty10 3<&- 3<&0 <&3

read -t 1 3<&- 3<&0 <&3হিসাবে একই read -t 0। এটি কেবল স্টিডিনের কাছ থেকে সময়সীমা সহ পাঠ করছে।
স্টাফেন চেজেলাস

1

এটি লগইন শেল এবং অ-ইন্টারেক্টিভ শেল থেকেও কাজ করে।

#!/bin/sh

# to avoid starting /bin/sleep each time we call sleep, 
# make our own using the read built in function
xsleep()
{
  read -t $1 -u 1
}

# usage
xsleep 3

এটি ম্যাক ওএস এক্স ভি 10.12.6
বি 01

1
এটি সুপারিশ করা হয় না। যদি একই সময়ে একাধিক স্ক্রিপ্টগুলি এটি ব্যবহার করে তবে তারা সবাই স্টিডিন পড়ার চেষ্টা করার সাথে সাথে তারা সমস্তই সাইনস্টপ হয়ে যায়। এটি অপেক্ষা করার সময় আপনার স্টিডিন ব্লক হয়ে যায়। এর জন্য স্টিডিন ব্যবহার করবেন না। আপনি নতুন নতুন ফাইল বর্ণনাকারী চান।
নরম্যাড করুন

1
@ নরমডাইজ করুন এখানে আরও একটি উত্তর রয়েছে ( unix.stackexchange.com/a/407383/147685 ) যা ফ্রি ফাইল বর্ণনাকারী ব্যবহারের উদ্বেগ নিয়ে কাজ করে। এর খালি ন্যূনতম সংস্করণটি read -t 10 <> <(:)
আমির

0

আপনার কি সত্যিই ফিফো দরকার? অন্য ফাইল ডেস্ক্রিপ্টারে স্টিডিনকে পুনঃনির্দেশ করাও কাজ করা উচিত।

{
echo line | while read line; do
   read -t 1 <&3
   echo "$line"
done
} 3<&- 3<&0

দ্বারা অনুপ্রাণিত: কিছুক্ষণ লুপের মধ্যে ব্যাশে ইনপুট পড়ুন


1
এটি একটি ঘুম করছে না, এটি এখনও টার্মিনাল থেকে স্টিডিন গ্রাস করছে।
jfg956

0

উল্লিখিত সমাধানগুলিতে সামান্য উন্নতি (যার ভিত্তিতে আমি এটি তৈরি করেছি)।

bash_sleep() {
    read -rt "${1?Specify sleep interval in seconds}" -u 1 <<<"" || :;
}

# sleep for 10 seconds
bash_sleep 10

একটি ফিফোর প্রয়োজন হ্রাস করা হয়েছে এবং তাই কোনও কাজ পরিষ্কার করার জন্য নেই।


1
এটি সুপারিশ করা হয় না। যদি একই সময়ে একাধিক স্ক্রিপ্টগুলি এটি ব্যবহার করে তবে তারা সবাই স্টিডিন পড়ার চেষ্টা করার সাথে সাথে তারা সমস্তই সাইনস্টপ হয়ে যায়। এটি অপেক্ষা করার সময় আপনার স্টিডিন ব্লক হয়ে যায়। এর জন্য স্টিডিন ব্যবহার করবেন না। আপনি নতুন নতুন ফাইল বর্ণনাকারী চান।
শে

@ নরমাদাইজ দয়া করে আপনি বিশদ বিবরণ দিতে বা আমাকে এমন একটি উত্সের দিকে নির্দেশ করতে পারেন যেখানে আমি এটি সম্পর্কে আরও পড়তে পারি।
কোডমেডিক

@ কোডেমেডিক এখানে আরও একটি উত্তর আছে ( unix.stackexchange.com/a/407383/147685 ) যা ফ্রি ফাইল বর্ণনাকারী ব্যবহারের উদ্বেগ নিয়ে কাজ করে। এর খালি ন্যূনতম সংস্করণটি read -t 10 <> <(:)
আমির
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.