ফাঁদ ব্যবহার করে নিশ্চিত প্রস্থান


9

আমি Ctrl+Cব্যবহারকারীর কাছ থেকে একটি নিশ্চয়তা চেয়ে সিগন্যালটি ফাঁদে দেওয়ার চেষ্টা করছি । ফাঁদ অংশ ভাল কাজ করে। কিন্তু একবার সংকেত আটকে গেলে, এটি সাধারণ সম্পাদনে ফিরে আসে না। পরিবর্তে, এটি স্ক্রিপ্টটি ছেড়ে দেয়। ব্যবহারকারী যখন কোনও চাপ না দেয় তখন এটি কীভাবে পুনরায় প্রয়োগ করা যায়।

এখানে আমার কোড

hell()
{
echo "Do you want to quit? Press 1 for yes and 0 for no";
read n;
if [ $n == 1 ]; then
exit 1;
fi
}

trap "hell" SIGINT

find /

উত্তর:


12

কি হচ্ছে

আপনি যখন Ctrl+ টিপেন C, SIGINTসিগন্যালটি পুরো অগ্রভাগের প্রক্রিয়া গোষ্ঠীতে সরবরাহ করা হয় । এখানে এটি findপ্রক্রিয়া এবং কলিং শেল প্রক্রিয়া উভয়কেই প্রেরণ করা হয়েছে । findতাত্ক্ষণিক প্রস্থান করে প্রতিক্রিয়া জানায় এবং শেলটি ফাঁদে কল করে প্রতিক্রিয়া জানায়।

ট্র্যাপের কোডটি যদি ফেরত আসে (যেমন কল দেয় না exit), সিগন্যাল দ্বারা বাধাগ্রস্থ হওয়ার পরে কমান্ডের সাথে মৃত্যুদন্ড কার্যকর হয়। এখানে, findকমান্ডটি স্ক্রিপ্টের শেষে আসার পরে , স্ক্রিপ্টটি তত্ক্ষণাতই প্রস্থান করা হবে। তবে আপনি অন্য কমান্ড যুক্ত করে 0 এবং 1 এন্ট্রি করার পার্থক্য দেখতে পাবেন:

find /
echo "find returned $?"

আপনি যা চান তা করার একটি উপায় (তবে সম্ভবত করা উচিত নয়)

তুমি যা চাও তাই করতে পারো; তবে আমার উত্তরের এই অংশটি একটি প্রকৃত সমস্যা সমাধানের চেয়ে শেল প্রোগ্রামিং আবিষ্কার সম্পর্কে আরও বেশি।

  • ডিজাইনের বিষয়টি হিসাবে, পুনরায় আরম্ভযোগ্য সংকেতটি আপনি সাধারণত তুলনামূলকভাবে সহজ প্রোগ্রামগুলির মধ্যে যে ধরণের তুলনামূলক সহজ প্রোগ্রামগুলির শেল স্ক্রিপ্টগুলি সাধারণত হন তা প্রত্যাশা করেন না। প্রত্যাশা যে Ctrl+ + Cস্ক্রিপ্ট মেরে ফেলবে।
  • আপনি নীচের দেখতে পাবেন, এটি শেল এর ক্ষমতা কিছুটা দূরে প্রসারিত।

আপনি হত্যা এড়াতে চান তাহলে find, আপনি এটা শুরু করতে পটভূমি : find / &। তারপরে waitবিল্টিনটি স্বাভাবিকভাবে প্রস্থান করার জন্য অপেক্ষা করুন to একটি সংকেত waitঅন্তর্নির্মিত বাধা দেবে , যা আপনি প্রচার করতে চান এমন সিগন্যাল না পাওয়া পর্যন্ত আপনি লুপে চালাতে পারেন। তারপরে killচাকরিটি মেরে ফেলুন।

hell () {
  echo "Do you want to quit? Press 1 for yes and 0 for no"
  read n
  if [ "$n" = 1 ]; then
    # Kill the job if it's running, then exit
    if [ -n "$job_pid" ]; then kill $job_pid; fi
    exit 1
  fi
}

job_pid=
trap "hell" SIGINT

# Start a demo job in the background
for i in 1 2 3 4 5; do date; sleep 1; done &
job_pid=$!
# Call wait in a loop; wait will return 0 if the job exits, and 128+$signum if interrupted by a signal.
while ! wait; do
  echo "resuming wait"
done
job_pid=
echo last exit code: $?

শেলের মধ্যে এই পদ্ধতির সীমাবদ্ধতা রয়েছে:

  • একটি দৌড় শর্ত রয়েছে: আপনি কাজটি শেষ হওয়ার ঠিক পরে কিন্তু লাইনের আগে Ctrl+ চাপলে সিগন্যাল হ্যান্ডলার মারার চেষ্টা করবে , তবে প্রক্রিয়াটি আর বিদ্যমান নেই (এমনকি একটি জম্বি হিসাবেও, কারণ ইতিমধ্যে এটি কাটা হয়েছে), এবং প্রক্রিয়াটি আইডি অন্য কোনও প্রক্রিয়া দ্বারা পুনরায় ব্যবহার করা যেতে পারে। এটি শেলের মধ্যে সহজেই ঠিক করা যায় না (সম্ভবত কোনও হ্যান্ডলার সেট করে ?)Cjob_pid=$jobpidwaitSIGCHLD
  • আপনার যদি কাজ থেকে রিটার্নের স্ট্যাটাসের প্রয়োজন হয় তবে আপনাকে wait $job_pidফর্মটি ব্যবহার করতে হবে। তবে আপনি আলাদা করতে পারবেন না " waitএকটি সংকেত দ্বারা বাধাগ্রস্থ হয়েছিল" থেকে "চাকুরীটি একটি সংকেত দ্বারা হত্যা করা হয়েছিল" (বা "রিটার্নের স্থিতি - 128 এর সাথে নিজের কাজটি সমাপ্ত করে", তবে এটি শেলের সাধারণ ঘটনা) প্রোগ্রামিং)।
  • এটি একসাথে একাধিক সাবজবগুলিতে সহজে প্রসারিত হবে না। মনে রাখবেন যে আপনি বেশিরভাগ শেল বাস্তবায়নের ক্ষেত্রে বেসিকগুলি ছাড়িয়ে গেলে ফাঁদ এবং সংকেতগুলির আচরণ প্রায়শই অবাক হয় only

এই সীমাবদ্ধতাগুলি কাটিয়ে উঠতে, পার্ল বা পাইথনের মতো কল্পিত ভাষা ব্যবহার করুন।

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