SIGINT এবং অনুরূপ ট্র্যাপ করার সময় প্রস্থান কোডগুলি রাখবেন?


14

যদি আমি প্রস্থানের আগে সিআরটিএল-সি (বা অনুরূপ) এবং ক্লিনআপ ধরার জন্য http://linuxcommand.org/wss0160.php#traptrap তে বর্ণিত যেমন ব্যবহার করি তবে আমি ফিরে আসা প্রস্থান কোডটি পরিবর্তন করছি।

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

উদাহরণ (ব্যাশে, তবে আমার প্রশ্নটিকে ব্যাশ-নির্দিষ্ট বিবেচনা করা উচিত নয়):

#!/bin/bash
trap 'echo EXIT;' EXIT
read -p 'If you ctrl-c me now my return code will be the default for SIGTERM. ' _
trap 'echo SIGINT; exit 1;' INT
read -p 'If you ctrl-c me now my return code will be 1. ' _

আউটপুট:

$ ./test.sh # doing ctrl-c for 1st read
If you ctrl-c me now my return code will be the default for SIGTERM.
$ echo $?
130
$ ./test.sh # doing ctrl-c for 2nd read
If you ctrl-c me now my return code will be the default for SIGTERM.
If you ctrl-c me now my return code will be 1. SIGINT 
EXIT
$ echo $?
1

(এটিকে আরও পজিক্স-কনফর্ম হিসাবে তৈরি করতে সরানোর জন্য সম্পাদিত))

(পরিবর্তে এটিকে বাশ স্ক্রিপ্ট তৈরি করতে আবার সম্পাদনা করা হয়েছে, আমার প্রশ্ন যদিও শেল-নির্দিষ্ট নয়))

অ-বহনযোগ্য "সাইন ইন" এর পক্ষে ফাঁদে ফেলার জন্য পোর্টেবল "INT" ব্যবহার করার জন্য সম্পাদিত।

অকেজো কোঁকড়ানো ধনুর্বন্ধনী অপসারণ এবং সম্ভাব্য সমাধান যুক্ত করতে সম্পাদিত।

হালনাগাদ:

হার্ডকডযুক্ত কিছু ত্রুটি কোডগুলি এবং এক্সিট ফাঁদে ফেলে কেবল এখনই আমি এটি সমাধান করেছি। এটি নির্দিষ্ট সিস্টেমে সমস্যাযুক্ত হতে পারে কারণ ত্রুটি কোডটি পৃথক হতে পারে বা এক্সিট ট্র্যাপটি সম্ভব না হলেও আমার ক্ষেত্রে এটি যথেষ্ট ঠিক OK

trap cleanup EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM

আপনার স্ক্রিপ্ট একটু অদ্ভুত দেখায়: আপনাকে বলতে readবর্তমান coprocess থেকে পড়তে এবং trap cmd SIGINTমান হিসেবে কাজ করবে না বলে যা আপনি ব্যবহার করা উচিত নয় trap cmd INT
সহজেই

হ্যাঁ হ্যাঁ, পসিক্সের অধীনে এটি অবশ্যই সাইন-উপসর্গ ছাড়াই।
পিএইচকে

ওফস, তবে তারপরে "রিড-পি" সমর্থিত হবে না, তাই আমি এটি ব্যাশের জন্য মানিয়ে নিতে চলেছি।
পিএইচকে

@ শচিলি: যদিও আপনি "কপ্রোসেস" বলতে চাইছেন তা আমি জানি না।
পিএইচকে

ওয়েল, কর্ন শেল ম্যান পেজটি বলেছে read -pযে বর্তমান কোপ্রোসেসের ইনপুটটি পড়ে।
চৌকস

উত্তর:


4

আপনাকে যা করতে হবে তা হ'ল আপনার ক্লিনআপ হ্যান্ডলারের ভিতরে থাকা এক্সিট হ্যান্ডলারটি পরিবর্তন করা । এখানে একটি উদাহরণ:

#!/bin/bash
cleanup() {
    echo trapped exit
    trap 'exit 0' EXIT
}
trap cleanup EXIT
read -p 'If you ctrl-c me now my return code will be the default for SIGTERM. '

আপনি কি trap cleanup INTপরিবর্তে বোঝাতে চেয়েছিলেন trap cleanup EXIT?
জেফ শ্যাচলার

আমি মনে করি আমি প্রস্থান করেছি শেষ পর্যন্ত প্রস্থানটি যখন ডাকা হয়, তবে তা হয়ে যায়, আমরা ফিরতি 0 দিয়ে প্রস্থান করার জন্য ফাঁদটি পরিবর্তন করি I আমি বিশ্বাস করি না যে সিগন্যাল হ্যান্ডলারগুলি পুনরাবৃত্তি হয়।
পাথুরে

ঠিক আছে, আপনার উদাহরণে আমি (সাইন) আইএনটি মোটেও আটকাচ্ছি না যা আসলে আমি চাই যা কিছু পরিষ্কার করার জন্য ব্যবহারকারী সিটিটিএল-সি এর মাধ্যমে আমার ইন্টারেক্টিভ স্ক্রিপ্ট থেকে বেরিয়ে আসছেন।
পিএইচকে

@ পিএফকে ঠিক আছে আমি মনে করি যদিও আপনি কীভাবে 0 বা অন্য কোনও মান যা আমি জড়ো করেছিলাম তা ফিরিয়ে আনতে বাধ্য করার ধারণাটি পেয়েছি তবে সমস্যা ছিল। আমি ধরে নিলাম আপনি নিজের সত্যিকারের ক্লিনআপ হ্যান্ডলারের ভিতরে ফাঁদটি নির্ধারণের জন্য কোডটি সামঞ্জস্য করতে সক্ষম হবেন যা সাইন ইন বলে।
পাথুরে

@ রকি: আমার লক্ষ্যটি হ'ল হ্যান্ডলারটি ছাড়াই সাধারণত যে প্রস্থান কোডটি আমার কাছে আসত তা না পরিবর্তন করার সময় একটি ট্র্যাপ হ্যান্ডলার রাখা ছিল। এখন আমি সাধারণভাবে আপনি যে প্রস্থান কোডটি পাবেন তা ফিরে আসতে পারলাম তবে সমস্যাটি হ'ল আমি এই ক্ষেত্রে সঠিক প্রস্থান কোডটি জানি না (যেমন থ্রেডে আমি লিঙ্ক করেছি এবং মেইউ থেকে পোস্টটি বেশ জটিল)। আপনার পোস্টটি এখনও সহায়ক ছিল I
পিএইচকে

9

প্রকৃতপক্ষে, ব্যাশের অভ্যন্তরীণ readবাধাকে বাশ দ্বারা চালিত কমান্ড বাধা দেওয়ার থেকে কিছুটা আলাদা বলে মনে হচ্ছে। সাধারণত, যখন আপনার লেখা trap, $?সেট করা হয় এবং আপনি এটি এবং একই মান প্রস্থান সংরক্ষণ করতে পারেন:

trap 'rc=$?; echo $rc SIGINT; exit $rc' INT
trap 'rc=$?; echo $rc EXIT; exit $rc' EXIT

যদি আপনার স্ক্রিপ্টটি কোনও কমান্ড sleep বা এমনকি একটি বিল্টিন লাইকের মতো কার্যকর করার সময় বাধা দেয় তবে waitআপনি দেখতে পাবেন

130 SIGINT
130 EXIT

এবং প্রস্থান কোডটি ১৩০ However তবে যাইহোক, read -pএটি $?0 (যেকোনভাবে আমার সংস্করণ 4.3.42 এর সংস্করণে) বলে মনে হচ্ছে।


readআমার রিলিজের পরিবর্তন ফাইল অনুসারে সিগন্যালগুলি হ্যান্ডলিংয়ের কাজ চলমান থাকতে পারে ... (/ usr / share / doc / bash / পরিবর্তনসমূহ)

এই সংস্করণ, bash-4.3-alpha এবং পূর্ববর্তী সংস্করণ, bash-4.2- প্রকাশের মধ্যে পরিবর্তন রয়েছে।

  1. বাশে নতুন বৈশিষ্ট্য

    দ। পিক্সিক্স মোডে থাকাকালীন, আটকে থাকা সংকেত দ্বারা 'পঠন' বাধা দেয়। ট্র্যাপ হ্যান্ডলারটি চালানোর পরে, 128+ সিগন্যাল রিটার্ন পড়ুন এবং আংশিক-পঠিত কোনও ইনপুট ফেলে দেয়।


ঠিক আছে, এটা সত্যিই অদ্ভুত। এটি ব্যাশ ৪.৩.৪২ (সাইগউইনের অধীনে) এর ইন্টারেক্টিভ শেলের সাথে 130 টি, একই স্কেলের নিচে 0 যখন কোনও স্ক্রিপ্ট এবং পসিক্স মোডে থাকে বা কোনও পার্থক্য করে না। তবে ড্যাশ এবং
ব্যস্তবক্সের

আমি পসিক্স মোডটি একটি ফাঁদ দিয়ে চেষ্টা করেছি যা প্রস্থান করতে পারে readনা এবং পরিবর্তন ফাইলটিতে উল্লিখিত (এটি আমার উত্তরে যুক্ত হয়েছে) এটি পুনরায় চালু করে । সুতরাং, এটি কাজ চলছে।
meuh

প্রস্থান কোড 130 হ'ল 100% নন-পোর্টেবল। বোর্ন শেল 128 + signoসিগন্যালের জন্য প্রস্থান কোড হিসাবে ব্যবহার করার সময় , ksh93 ব্যবহার করে 256 + signo
পসিক্স

@ স্কিলি ট্রু, মূল পোস্টটিতে আমি যুক্ত থ্রেডে উল্লিখিত ( ইউনিক্স.স্ট্যাকেক্সেঞ্জাওয়েজ / সেকশনস / ৯৯১১২ )।
পিএইচকে

6

$?ট্র্যাফ হ্যান্ডলারের প্রবেশের পরে যে কোনও সাধারণ সিগন্যাল প্রস্থান কোড পাওয়া যাবে :

sig_handler() {
    exit_status=$?  # Eg 130 for SIGINT, 128 + (2 == SIGINT)
    echo "Doing signal-specific up"
    exit "$exit_status"
}
trap sig_handler INT HUP TERM QUIT

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


এটি বেশিরভাগ শাঁসের জন্য প্রযোজ্য? খুব সুন্দর. localযদিও পসিক্স নয়।
phk

1
সম্পাদনা করা হয়েছে। আমি ছাড়া অন্য পরীক্ষা করিনি {ba,z}sh। আফাইক, নির্বিশেষে এটি করা সবচেয়ে ভাল can
টম হেল

এটি ড্যাশগুলিতে কাজ করে না ( $?প্রাপ্ত সংকেত যা হ'ল 1)।
মুনসুইপ

2

কেবল কিছু ত্রুটি কোড ফিরিয়ে আনুন সাইন ইন দ্বারা একটি প্রস্থান অনুকরণের জন্য যথেষ্ট নয়। আমি অবাক হয়েছি যে এখনও পর্যন্ত কেউ এটি উল্লেখ করেনি। আরও পড়া: https://www.cons.org/cracauer/sigint.html

সঠিক উপায়টি হ'ল:

for sig in EXIT ABRT HUP INT PIPE QUIT TERM; do
    trap "cleanup;
          [ $sig  = EXIT ] && normal_exit_only_cleanup;
          [ $sig != EXIT ] && trap - $sig EXIT && kill -s $sig $$
         " $sig
done

এটি বাশ, ড্যাশ এবং zsh এর সাথে কাজ করে। আরও বহনযোগ্যতার জন্য আপনাকে সংখ্যার সিগন্যাল স্পেসিফিকেশন ব্যবহার করতে হবে (অন্যদিকে zsh killকমান্ডের জন্য একটি স্ট্রিং প্যারামিটার আশা করে ...)

EXITসিগন্যালের বিশেষ চিকিত্সাটিও নোট করুন । এটি কোনও শেল (যথা বাশ) EXITসম্ভবত কোনও সংকেতের জন্য ট্র্যাপগুলি কার্যকর করে (সেই সংকেতটিতে সম্ভবত সংজ্ঞায়িত ফাঁদের পরে ) এর কারণে এটি ঘটে । EXITফাঁদ পুনরায় সেট করা বাধা দেয়।

শুধুমাত্র "সাধারণ" প্রস্থানের সময় কোড কার্যকর করা হচ্ছে

চেকটি [ $sig = EXIT ]কেবলমাত্র সাধারণ (অ-সিগন্যালড) প্রস্থান করতে কোড সম্পাদন করার অনুমতি দেয়। যাইহোক, সমস্ত সিগন্যালের ফাঁদ থাকতে হবে যা শেষ সময়ে সেই ফাঁদটি পুনরায় সেট করে EXIT; normal_exit_only_cleanupএমন সংকেতগুলির জন্যও ডেকে আনা হবে যা তা নয়। এটি একটি প্রস্থান মাধ্যমে চালানো হবে set -e। এটি আটকে রেখে ERR(যা ড্যাশ দ্বারা সমর্থিত নয়) এবং এর [ $sig = ERR ]আগে একটি চেক যুক্ত করে ঠিক করা যায় kill

সরলিকৃত বাশ-কেবল সংস্করণ

অন্যদিকে, এই আচরণটির অর্থ ব্যাশের মধ্যে আপনি কেবল পারেন

trap cleanup EXIT

কিছু ক্লিনআপ কোড কার্যকর করতে এবং প্রস্থান স্থিতি ধরে রাখতে।

সম্পাদিত

  • "এক্সিট সব কিছু ফাঁদে ফেলে" বাশের আচরণকে বিস্তৃত করুন

  • কিল সিগন্যাল সরান, যা আটকা যায় না

  • সিগন্যালের নামগুলি থেকে SIG উপসর্গগুলি সরান

  • চেষ্টা করবেন না kill -s EXIT

  • set -eঅ্যাকাউন্টে / ERR নিন


সিগন্যালগুলিকে ফাঁদে ফেলে এমন একটি প্রোগ্রাম এমনভাবে শেষ করা উচিত যে এটি একটি সংকেত পেয়েছে এই সত্যটি সংরক্ষণ করে no উদাহরণস্বরূপ কোনও প্রোগ্রাম ঘোষণা করতে পারে যে SIGINTপ্রেরণই এটি বন্ধ করার উপায় এবং এটি 0 দিয়ে প্রস্থান করার সিদ্ধান্ত নিতে পারে যদি এটি ত্রুটি ছাড়াই শেষ করতে সক্ষম হয় বা অন্য কোনও ত্রুটি কোড যদি এটি পরিষ্কারভাবে বন্ধ না করে। একটা উদাহরণ: top। রান করুন top; echo $?এবং তারপরে Ctrl-C টিপুন। স্ক্রিনে ফেলে দেওয়া স্ট্যাটাসটি 0 হবে
লুই

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