আমি কীভাবে শেল স্ক্রিপ্টে কোনও ফাইলের জন্য অপেক্ষা করব?


15

আমি একটি শেল স্ক্রিপ্ট লেখার চেষ্টা করছি যা /tmpডাকা ডিরেক্টরিতে একটি ফাইল উপস্থিত হওয়ার জন্য অপেক্ষা করবে sleep.txtএবং এটি সন্ধান পেলে প্রোগ্রামটি বন্ধ হয়ে যাবে, অন্যথায় আমি চাইছি ফাইলটি উপস্থিত না হওয়া পর্যন্ত প্রোগ্রামটি ঘুমের মধ্যে (স্থগিত) অবস্থায় থাকবে I । এখন, আমি ধরে নিচ্ছি যে আমি একটি পরীক্ষা কমান্ড ব্যবহার করব। সুতরাং, মত কিছু

(if [ -f "/tmp/sleep.txt" ]; 
then stop 
   else sleep.)

আমি শেল স্ক্রিপ্ট লেখার জন্য একেবারে নতুন এবং কোনও সাহায্যের প্রশংসা করা হয়!


তাকান $MAILPATH
মাইকজার্ভ

উত্তর:


23

লিনাক্সের অধীনে, আপনি ডিরেক্টরিতে কোনও ফাইল উপস্থিতির জন্য দক্ষতার সাথে অপেক্ষা করতে ইনোটাইফাই কার্নেল সাবসিস্টেমটি ব্যবহার করতে পারেন :

while read i; do if [ "$i" = sleep.txt ]; then break; fi; done \
   < <(inotifywait  -e create,open --format '%f' --quiet /tmp --monitor)
# script execution continues ...

( <()আউটপুট পুনর্নির্দেশ সিনট্যাক্সের জন্য ব্যাশ ধরে )

নির্দিষ্ট সময়ের ব্যবধানের মত নির্বাচনের তুলনায় এই পদ্ধতির সুবিধা

while [ ! -f /tmp/sleep.txt ]; do sleep 1; done
# script execution continues ...

কার্নেল আরও ঘুমায়। create,openস্ক্রিপ্টের মতো কোনও ইনোটিফাই ইভেন্টের স্পেসিফিকেশন সহ যখন কোনও ফাইল /tmpতৈরি করা বা খোলা হয় তখন তা কার্যকর করার জন্য নির্ধারিত হয়। নির্দিষ্ট সময় ব্যবধানের পোলিংয়ের মাধ্যমে আপনি প্রতিটি সময় বৃদ্ধির জন্য সিপিইউ চক্র নষ্ট করেন।

ফাইলটি ইতিমধ্যে উপস্থিত থাকলে আমি openনিবন্ধকরণের জন্য ইভেন্টটি অন্তর্ভুক্ত করেছি touch /tmp/sleep.txt


ধন্যবাদ, এটি দুর্দান্ত! আপনি যদি ফাইলটির নাম জানেন তবে আপনাকে কেন লুপের প্রয়োজন হবে? কেন যে স্রেফ হতে পারে না inotifywait -e create,open --format '%f' --quiet /tmp/sleep.txt --monitor > /dev/null ; # continues once /tmp/sleep.txt is created/opened?
এনএইচডালি

ওহ, জে.কে. টুলটি ইনস্টল করার পরে আমি এখন বুঝতে পারি। inotifywaitনিজেই একটি সময় লুপ হয় এবং ফাইলটি প্রতিবার খুলতে / তৈরি করা গেলে এটি একটি লাইন আউটপুট করে। সুতরাং এটি পরিবর্তিত হওয়ার সময় আপনার ভাঙ্গার প্রয়োজন break
এনএইচডিলে

ব্যতীত এটি একটি রেস শর্ত তৈরি করে - পরীক্ষা-ই / স্লিপ সংস্করণের বিপরীতে। লুপটি প্রবেশের আগে ফাইলটি তৈরি হবে না এমন গ্যারান্টি দেওয়ার কোনও উপায় নেই - এই ক্ষেত্রে ইভেন্টটি মিস হবে। আপনাকে লুপের আগে (ঘুম 1; [[-e /tmp/sleep.txt]] && স্পর্শ /tmp/sleep.txt;) এর মতো কিছু যুক্ত করতে হবে। প্রকৃত ব্যবসায়ের যুক্তির উপর নির্ভর করে কোনটি অবশ্যই রাস্তায় সমস্যা তৈরি করতে পারে
এন-অ্যালেক্সান্ডার

@ এন-আলেকজান্দার ওয়েল, উত্তরটি ধরে নিয়েছে যে প্রক্রিয়াটি শুরু করার আগে আপনি স্নিপেটটি কার্যকর করেছিলেন যা sleep.txtকোনও এক সময় উত্পাদিত হবে । সুতরাং, কোন জাতি শর্ত। প্রশ্নটি আপনার মনে থাকা দৃশ্যে ইঙ্গিত করার কোনও কিছুই ধারণ করে না।
ম্যাক্সচলেপজিগ

বিপরীতে @ ম্যাক্সচলেপজিগ অর্ডার প্রয়োগ করা না হলে এটি ধরে নেওয়া যায় না। বুনিয়াদি।
এন-অ্যালেক্সান্ডার

10

লুপটিতে কেবল আপনার পরীক্ষাটি রাখুন while:

while [ ! -f /tmp/sleep.txt ]; do sleep 1; done
# next command

আপনি যেমনটি লিখেছেন, এটি হ'ল যুক্তি: ফাইলটির অস্তিত্ব নেই, স্ক্রিপ্টটি ঘুমাবে। অন্যথায়, এটি করা হয়। সঠিক?
মো গাইনজ

@ মোগেইনজ সঠিক sleepপ্রতিটি পুনরাবৃত্তির জন্য অপেক্ষা করতে সেকেন্ডের পরে সংখ্যাটি - আপনি আপনার প্রয়োজনের উপর নির্ভর করে এটি পরিবর্তন করতে পারেন।
jimmij

7

inotifywaitএখনও অবধি দেওয়া কিছু ভিত্তিক পদ্ধতির সাথে কয়েকটি সমস্যা রয়েছে :

  • তারা কোনও sleep.txtফাইল খুঁজে পেতে ব্যর্থ হয় যা প্রথমে অস্থায়ী নাম হিসাবে তৈরি করা হয়েছিল এবং তারপরে পুনরায় নামকরণ করা হয়েছে sleep.txtmoved_toইভেন্টগুলি ছাড়াও একটিরও ম্যাচ করা দরকারcreate
  • ফাইলের নামগুলিতে নিউলাইন অক্ষর থাকতে পারে, ডিলিমিট করা ফাইলের নাম মুদ্রণ করা যথেষ্ট নয় যে sleep.txtএটি তৈরি হয়েছে কিনা তা নির্ধারণ করার জন্য । foo\nsleep.txt\nbarউদাহরণস্বরূপ যদি একটি ফাইল তৈরি করা হয়?
  • ফাইল তৈরি করা হয় কি যদি আগে inotifywait শুরু হয়েছে এবং ঘড়ির ইনস্টল? তারপরে inotifywaitএখানে থাকা একটি ফাইলের জন্য চিরকাল অপেক্ষা করবে। ঘড়িটি ইনস্টল হওয়ার পরে আপনার ফাইলটি আগে থেকেই নেই তা নিশ্চিত করা দরকার।
  • inotifywaitফাইল সন্ধানের পরে কিছু সমাধান চলমান ছেড়ে যায় (কমপক্ষে অন্য একটি ফাইল তৈরি হওয়া অবধি)।

এগুলিকে সম্বোধন করার জন্য, আপনি এটি করতে পারেন:

sh -c 'echo "$$" &&
        LC_ALL=C exec inotifywait -me create,moved_to --format=/%f/ . 2>&1' | {
  IFS= read pid &&
    while IFS= read -r line && [ "$line" != "Watches established." ]; do
      : wait for watches to be established
    done
  [ -e sleep.txt ] || [ -L sleep.txt ] || grep -qxF /sleep.txt/ && kill "$pid"
}

নোট করুন যে আমরা sleep.txtবর্তমান ডিরেক্টরিটি তৈরি করার জন্য লক্ষ্য করছি , .(যাতে আপনি cd /tmp || exitআপনার উদাহরণের আগে একটি কাজ করতে চান )। বর্তমান ডিরেক্টরিটি কখনই পরিবর্তিত হয় না, সুতরাং যখন পাইপ লাইনটি সফলভাবে ফিরে আসে, এটি sleep.txtবর্তমান ডিরেক্টরিতে তৈরি করা হয়েছে।

অবশ্যই, আপনি উপরের .সাথে প্রতিস্থাপন করতে পারেন /tmp, তবে inotifywaitচলমান অবস্থায়, /tmpবেশ কয়েকবার নতুন নামকরণ করা যেতে পারে ( /tmpসাধারণ ক্ষেত্রে বিবেচনার জন্য কিছু নয়) বা এটিতে একটি নতুন ফাইল সিস্টেম স্থাপন করা হয়েছে, সুতরাং পাইপলাইনটি ফিরে আসলে এটি নাও পারে একটি হতে /tmp/sleep.txtতৈরি করা হয়েছে কিন্তু একটি /new-name-for-the-original-tmp/sleep.txtপরিবর্তে। /tmpব্যবধানে একটি নতুন ডিরেক্টরিও তৈরি করা যেত এবং এটি একটিও পর্যবেক্ষণ করা হত না, সুতরাং sleep.txtসেখানে একটি তৈরি করা সনাক্ত করা যায়নি।


1

গৃহীত উত্তরটি সত্যই কাজ করে (ধন্যবাদ ম্যাক্সচ্লেপজিগ) তবে আপনার স্ক্রিপ্টটি বের না হওয়া অবধি পটভূমিতে ইনটফাইয়েট পর্যবেক্ষণ ছেড়ে দেয়। আপনার প্রয়োজনীয়তার সাথে ঠিক মেলে একমাত্র উত্তর (যেমন ঘুম / টেক্সটের অভ্যন্তরে / টিএমপি দেখানোর জন্য অপেক্ষা করা) স্টিফেনের মনে হয়, যদি ইনোটেফাইয়েট দ্বারা নিরীক্ষণ করা ডিরেক্টরিটি বিন্দু (।) থেকে '/ টিএমপি' পরিবর্তন করা হয়।

তবে, আপনি যদি নিজের ঘুম.টিএসটি পতাকা লাগানোর জন্য কেবলমাত্র একটি অস্থায়ী ডিরেক্টরি ব্যবহার করতে ইচ্ছুক থাকেন এবং বাজি রাখতে পারেন যে অন্য কেউ সেই ডিরেক্টরিতে কোনও ফাইল রাখবে না, কেবল ফাইল তৈরির জন্য এই ডিরেক্টরিটি দেখার জন্য ইনোটিফাইয়েটকে বলা যথেষ্ট হবে:

প্রথম পদক্ষেপ: আপনি যে ডিরেক্টরিটি পর্যবেক্ষণ করবেন তা তৈরি করুন:

directoryToPutSleepFile=$(mktemp -d)

দ্বিতীয় পদক্ষেপ: ডিরেক্টরিটি সত্যই সেখানে আছে তা নিশ্চিত করুন

until [ -d $directoryToPutSleepFile ]; do sleep 0.1; done

তৃতীয় পদক্ষেপ: কোনও ফাইল ভিতরে না দেখানো পর্যন্ত অপেক্ষা করুন $directoryToPutSleepFile

inotifywait -e create --format '%f' --quiet $directoryToPutSleepFile

আপনি যে ফাইলটি রাখবেন তার $directoryToPutSleepFileনাম দেওয়া যেতে পারে ঘুম t টেক্সট জাগ্রত.txt, যাই হোক না কেন। আপনার স্ক্রিপ্টের মধ্যে কোনও ফাইল তৈরি হওয়ার মুহুর্তটি বিবৃতিটির $directoryToPutSleepFileঅতীত অবিরত থাকবে inotifywait


1
তবে এটি ফাইলটির সৃষ্টি হতে পারে না, যদি এর আগে আরও একটি তৈরি করা হয়েছিল, যার ফলে sleep.txtদুটি ইনোটিফাইয়েট অনুরোধগুলি অন্তর্নিহিতদের মধ্যে তৈরি হয়েছিল।
স্টাফেন চেজেলাস

এটির সমাধানের বিকল্প পদ্ধতির জন্য আমার উত্তরটি দেখুন ।
স্টাফেন চেজেলাস

আমার কোড চেষ্টা করুন। inotifywait কেবল একবার ডাকা হয়। যখন ঘুম ডট টেক্সট তৈরি করা হয় (বা ইতিমধ্যে সেখানে থাকলে পড়ুন / লিখিত থাকে), ইনোটিফাইয়েট আউটপুট "স্লিপ.টেক্সট" দেয় এবং 'সম্পন্ন' স্টেটমেন্টের পরে কার্যকর হয়।
নিকোলোস

নামক কোনও ফাইল তৈরি না হওয়া পর্যন্ত এটি বেশ কয়েকবার চাওয়া হয়েছে sleep.txt। উদাহরণস্বরূপ চেষ্টা করুন touch /tmp/foo /tmp/sleep.txt, তারপরে একটি উদাহরণ inotifywaitরিপোর্ট করবে fooএবং প্রস্থান করবে এবং পরবর্তী ইনোটিফয়েট শুরু হওয়ার সাথে সাথে ঘুম.txt ইতিমধ্যে অনেক আগে থেকেই থাকবে তাই ইনোটিফয়েট এটির আবিষ্কারটি সনাক্ত করতে পারে না।
স্টাফেন চেজেলাস

আপনি একাধিক অনুরোধ সম্পর্কে ঠিক বলেছেন: / টিএমপি এর অধীনে তৈরি প্রতিটি ফাইলের জন্য একটি অনুরোধ। আমি আমার উত্তর আপডেট। আপনার মন্তব্যের জন্য ধন্যবাদ.
নিকোলোস

0

সাধারণ টেস্ট / স্লিপ লুপকে বিশ্বাসযোগ্য ছাড়া কিছুই করা বেশ শক্ত। মূল সমস্যাটি হ'ল পরীক্ষাটি ফাইলটি তৈরির সাথে দৌড়াদৌড়ি করবে - যদি পরীক্ষাটি পুনরাবৃত্তি না করা হয় তবে ক্রিয়েট ইভেন্টটি মিস করা যায় না। এটি বেশিরভাগ ক্ষেত্রেই আপনার সেরা বাজি যেখানে আপনি শেলটি দিয়ে শুরু করতে চাইছেন:

#!/bin/bash
while [[ ! -e /tmp/file ]] ; do
    sleep 1
done

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


2
এটি জিমমিজের উত্তরের একটি সদৃশ মাত্র ।
ম্যাক্সচলেপজিগ

0

ম্যাক্সচ্লেপজিগের স্বীকৃত উত্তরের উপর ভিত্তি করে (এবং /superuser/270529/monitor-a-file-until-a-string-is-found- এ গৃহীত উত্তরের একটি ধারণা ) আমি নিম্নলিখিত উন্নত প্রস্তাব দিই ( আমার দৃষ্টিতে) উত্তর যা সময়সীমার সাথেও কাজ করতে পারে:

# Enable pipefail, so if the left side of the pipe fails it does not get silently ignored
set -o pipefail
( timeout 120 inotifywait -e create,open --format '%f' --quiet /tmp --monitor & ) | while read i; do if [ "$i" == 'sleep.txt' ]; then break; fi; done
EXIT_STATUS=$?
if [ "${EXIT_STATUS}" == '124' ]; then
  echo "Timeout happened"
fi

যদি প্রদত্ত সময়সীমার মধ্যে ফাইলটি তৈরি / খোলা না যায়, তবে প্রস্থান স্থিতিটি 124 (সময়সীমা ডকুমেন্টেশন (ম্যান পৃষ্ঠা)) হিসাবে রয়েছে। যদি এটি তৈরি / খোলা হয়ে যায় তবে প্রস্থান স্থিতি 0 (সাফল্য)।

হ্যাঁ, ইনোটিফয়েট এই উপ-শেলটিতে এইভাবে চালিত হয় এবং সেই উপ-শেলটি কেবল তখনই শেষ হওয়া শেষ হবে যখন সময়সীমা শেষ হয় বা যখন মূল স্ক্রিপ্টটি প্রস্থান হয় (যেটি প্রথমে আসে)।

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