উত্তর:
কিছু গণ্ডগোল পরিষ্কার করতে, trap
ব্যবহার করা যেতে পারে। এটি নির্দিষ্ট সংকেত এলে সম্পাদিত সামগ্রীর তালিকা সরবরাহ করতে পারে:
trap "echo hello" SIGINT
তবে শেলটি বেরিয়ে আসলে কিছু কার্যকর করতে ব্যবহার করা যেতে পারে:
trap "killall background" EXIT
এটি একটি অন্তর্নির্মিত, তাই help trap
আপনাকে তথ্য দেবে ( ব্যাশের সাথে কাজ করে)। আপনি যদি কেবল পটভূমির কাজগুলিই হত্যা করতে চান তবে আপনি এটি করতে পারেন
trap 'kill $(jobs -p)' EXIT
একা ব্যবহার '
করার জন্য সতর্কতা অবলম্বন করুন, শেলটি $()
অবিলম্বে প্রতিস্থাপন থেকে রোধ করতে ।
kill $(jobs -p)
ড্যাশে কাজ করে না, কারণ এটি একটি
killall background
একটি স্থানধারক হতে অনুমিত? background
ম্যান পেজে নেই ...
এটি আমার পক্ষে কাজ করেছে (মন্তব্যকারীদের কাছে উন্নত ধন্যবাদ):
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
4.3.30(1)-release
এটি ওএসএক্স-এ চালিয়েছি এবং এটি উবুন্টুতেও নিশ্চিত হয়ে গেছে । একটি ওভোভিয়াস ওকারাউন্ড রয়েছে , যদিও :)
-$$
। এটি '- <PID> to যেমন মূল্যায়ন করে -1234
। কিল ম্যানপেজে // বিল্টইন ম্যানপেজে একটি শীর্ষস্থানীয় ড্যাশ প্রেরণের জন্য সংকেত নির্দিষ্ট করে। যাইহোক - সম্ভবত এটি অবরুদ্ধ করে, তবে তারপরে নেতৃত্বের ড্যাশটি অন্যথায় শর্তহীন is কোন সাহায্য?
man 2 kill
, যা ব্যাখ্যা করে যে যখন কোনও পিআইডি নেতিবাচক থাকে তখন প্রদত্ত আইডি ( en.wikedia.org/wiki/Process_group ) সহ প্রক্রিয়া গোষ্ঠীর সমস্ত প্রক্রিয়াতে সংকেত প্রেরণ করা হয় । এটি বিভ্রান্তিকর যে এটিতে man 1 kill
বা উল্লেখ করা হয়নি man bash
এবং ডকুমেন্টেশনে একটি বাগ হিসাবে বিবেচিত হতে পারে।
আপডেট: https://stackoverflow.com/a/53714583/302079 প্রস্থান স্থিতি এবং একটি ক্লিনআপ ফাংশন যোগ করে এটি উন্নত করে।
trap "exit" INT TERM
trap "kill 0" EXIT
রূপান্তর INT
এবং TERM
প্রস্থান কেন ? কারণ উভয়েরই kill 0
অসীম লুপটি প্রবেশ না করেই ট্রিগার করা উচিত ।
কেন ট্রিগার kill 0
উপর EXIT
? কারণ সাধারণ স্ক্রিপ্টের প্রস্থানটিও ট্রিগার করা উচিত kill 0
।
কেন kill 0
? কারণ নেস্টেড সাবশেলগুলি পাশাপাশি হত্যা করা দরকার। এটি পুরো প্রক্রিয়া গাছটি নামিয়ে ফেলবে ।
kill 0
বোঝায় / করায় সে সম্পর্কে আপনি আরও প্রসারিত করতে পারেন?
ফাঁদ 'কিল $ (জব -২)' প্রস্থান করুন
আমি জোহানেসের উত্তরে কেবলমাত্র সামান্য পরিবর্তন করব এবং চাকরির ব্যবহারটি চলমান প্রক্রিয়াগুলিতে সীমাবদ্ধ করতে এবং তালিকায় আরও কয়েকটি সংকেত যোগ করতে:
trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT
trap 'kill 0' SIGINT SIGTERM EXIT
সমাধান বর্ণিত @ tokland এর উত্তর সত্যিই চমৎকার, কিন্তু সর্বশেষ ব্যাশ একটি segmantation দোষ সঙ্গে বিপর্যস্ত যখন এটি ব্যবহার করে। কারণ বাশ, ভি। ৪.৩ থেকে শুরু করে ফাঁদ পুনরাবৃত্তি করার অনুমতি দেয়, যা এই ক্ষেত্রে অসীম হয়ে ওঠে:
SIGINT
বা SIGTERM
বা EXIT
;kill 0
, যা SIGTERM
শেল নিজেই সহ গ্রুপে সমস্ত প্রক্রিয়াগুলিতে প্রেরণ করে;এই ফাঁদটি ম্যানুয়ালি করে নিবন্ধভুক্ত করে কাজ করা যেতে পারে:
trap 'trap - SIGTERM && kill 0' SIGINT SIGTERM EXIT
আরও অভিনব উপায়, এটি পুনরুদ্ধার করা সিগন্যাল মুদ্রণ করতে দেয় এবং "সমাপ্ত:" বার্তাগুলি এড়িয়ে চলে:
#!/usr/bin/env bash
trap_with_arg() { # from https://stackoverflow.com/a/2183063/804678
local func="$1"; shift
for sig in "$@"; do
trap "$func $sig" "$sig"
done
}
stop() {
trap - SIGINT EXIT
printf '\n%s\n' "recieved $1, killing children"
kill -s SIGINT 0
}
trap_with_arg 'stop' EXIT SIGINT SIGTERM SIGHUP
{ i=0; while (( ++i )); do sleep 0.5 && echo "a: $i"; done } &
{ i=0; while (( ++i )); do sleep 0.6 && echo "b: $i"; done } &
while true; do read; done
ইউপিডি : সংক্ষিপ্ত উদাহরণ যুক্ত; stop
অযৌক্তিক সংকেতকে ডি-ট্র্যাপিং-এ আউটপুট থেকে "টার্মিনেটেড:" বার্তাগুলি লুকানোর জন্য ক্রিয়াকলাপ উন্নত করা হয়েছে । পরামর্শের জন্য ধন্যবাদ ট্রেভর বয়ড স্মিথ !
stop()
সিগন্যাল নম্বর হিসাবে প্রথম যুক্তি প্রদান কিন্তু তারপরে আপনি হার্ডকোড যা সংকেত বাতিল করা হচ্ছে। সিগন্যালগুলি নিবন্ধভুক্ত হওয়ার চেয়ে হার্ডকোড না করে আপনি প্রথম যুক্তিটি stop()
ফাংশনে নিবন্ধভুক্ত করার জন্য ব্যবহার করতে পারেন ( এটি করলে সম্ভাব্যভাবে অন্যান্য পুনরাবৃত্ত সংকেতগুলি থামানো হবে (3 হার্ডকোডযুক্ত ব্যতীত))।
SIGINT
তবে kill 0
প্রেরণ করে SIGTERM
যা আবার আটকা পড়ে। এটি অসীম পুনরাবৃত্তি তৈরি করবে না, যদিও, SIGTERM
দ্বিতীয় stop
কল করার সময় এটি আটকা পড়বে ।
trap - $1 && kill -s $1 0
আরও ভাল কাজ করা উচিত। আমি এই উত্তরটি পরীক্ষা করে আপডেট করব। সুন্দর ধারণা জন্য আপনাকে ধন্যবাদ! :)
trap - $1 && kill -s $1 0
খুব কাজ করে না, কারণ আমরা মারতে পারি না EXIT
। তবে ডি-ট্র্যাপটি করা সত্যই যথেষ্ট TERM
, কারণ kill
ডিফল্টরূপে এই সংকেত প্রেরণ করে।
EXIT
, trap
সিগন্যাল-হ্যান্ডলারটি সর্বদা কেবল একবারই কার্যকর করা হয়।
নিরাপদে থাকাকালীন পরিষ্কার-পরিচ্ছন্নতার ফাংশনটি সংজ্ঞায়িত করা এবং ফাঁদ থেকে কল করা ভাল বলে মনে করি:
cleanup() {
local pids=$(jobs -pr)
[ -n "$pids" ] && kill $pids
}
trap "cleanup" INT QUIT TERM EXIT [...]
বা পুরোপুরি ফাংশন এড়ানো:
trap '[ -n "$(jobs -pr)" ] && kill $(jobs -pr)' INT QUIT TERM EXIT [...]
কেন? কারণ কেবল ব্যবহার করে trap 'kill $(jobs -pr)' [...]
এক ধরে নেয় যে সেখানে হবে যখন ফাঁদ শর্ত সংকেত হয় চলমান পটভূমি কাজ হবে। যখন কোনও চাকরি নেই তারা নিম্নলিখিত (বা অনুরূপ) বার্তাটি দেখতে পাবে:
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
কারণ jobs -pr
খালি - আমি সেই 'ফাঁদে' (পাং উদ্দেশ্যে) শেষ করেছি।
[ -n "$(jobs -pr)" ]
কেসটি আমার বাশে কাজ করে না। আমি জিএনইউ ব্যাশ, সংস্করণ 4.2.46 (2) -রিলেজ (x86_64-redhat-linux-gnu) ব্যবহার করি। "হত্যা: ব্যবহার" বার্তাটি পপ আপ করে রাখে।
jobs -pr
এটি ব্যাকগ্রাউন্ড প্রক্রিয়াগুলির বাচ্চাদের পিআইডি ফিরিয়ে দেয় না এর সাথে করা উচিত । এটি পুরো প্রক্রিয়া গাছটি ছিন্ন করে না, কেবল শিকড়গুলি ছাঁটাই করে।
একটি দুর্দান্ত সংস্করণ যা লিনাক্স, বিএসডি এবং ম্যাকোস এক্স এর অধীনে কাজ করে First
KillJobs() {
for job in $(jobs -p); do
kill -s SIGTERM $job > /dev/null 2>&1 || (sleep 10 && kill -9 $job > /dev/null 2>&1 &)
done
}
TrapQuit() {
# Whatever you need to clean here
KillJobs
}
trap TrapQuit EXIT
দয়া করে মনে রাখবেন যে চাকরিতে গ্র্যান্ড বাচ্চাদের প্রক্রিয়া অন্তর্ভুক্ত নয়।
function cleanup_func {
sleep 0.5
echo cleanup
}
trap "exit \$exit_code" INT TERM
trap "exit_code=\$?; cleanup_func; kill 0" EXIT
# exit 1
# exit 0
Https://stackoverflow.com/a/22644006/10082476 এর মতো তবে যোগ হওয়া প্রস্থান-কোড সহ
exit_code
থেকে আসে কোথা থেকে INT TERM
?
জবস -p সাব-শেলটিতে কল করা থাকলে সমস্ত শেলগুলিতে কাজ করে না, সম্ভবত যদি না তার আউটপুট কোনও ফাইলে পুনঃনির্দেশিত হয় তবে পাইপ না হয়। (আমি ধরে নিলাম এটি মূলত কেবল ইন্টারেক্টিভ ব্যবহারের জন্যই হয়েছিল))
নিম্নলিখিত সম্পর্কে কি:
trap 'while kill %% 2>/dev/null; do jobs > /dev/null; done' INT TERM EXIT [...]
দেবিয়ান ড্যাশ শেলের সাথে "জবস" এ কল করা দরকার, যা অনুপস্থিত থাকলে বর্তমান কাজ ("%%") আপডেট করতে ব্যর্থ।
trap 'echo in trap; set -x; trap - TERM EXIT; while kill %% 2>/dev/null; do jobs > /dev/null; done; set +x' INT TERM EXIT; sleep 100 & while true; do printf .; sleep 1; done
যদি আপনি এটিকে ব্যাশে চালান (5.0.3) এবং সমাপ্ত করার চেষ্টা করেন তবে মনে হয় অসীম লুপ রয়েছে। তবে আপনি যদি আবার এটি বন্ধ করেন তবে এটি কাজ করে। এমনকি ড্যাশ দ্বারা (0.5.10.2-6) আপনাকে এটি দুটিবার শেষ করতে হবে।
Http://veithen.github.io/2014/11/16/sigterm-propagation.html থেকে জ্ঞানের সাথে মিলিয়ে আমি @ টোকল্যান্ডের উত্তরটির একটি রূপান্তর করেছি যখন আমি লক্ষ্য করেছি যে trap
আমি অগ্রভাগের প্রক্রিয়া চালাচ্ছি তবে ট্রিগার হয় না (এর সাথে পটভূমি নেই &
):
#!/bin/bash
# killable-shell.sh: Kills itself and all children (the whole process group) when killed.
# Adapted from http://stackoverflow.com/a/2173421 and http://veithen.github.io/2014/11/16/sigterm-propagation.html
# Note: Does not work (and cannot work) when the shell itself is killed with SIGKILL, for then the trap is not triggered.
trap "trap - SIGTERM && echo 'Caught SIGTERM, sending SIGTERM to process group' && kill -- -$$" SIGINT SIGTERM EXIT
echo $@
"$@" &
PID=$!
wait $PID
trap - SIGINT SIGTERM EXIT
wait $PID
এটি কাজ উদাহরণ:
$ bash killable-shell.sh sleep 100
sleep 100
^Z
[1] + 31568 suspended bash killable-shell.sh sleep 100
$ ps aux | grep "sleep"
niklas 31568 0.0 0.0 19640 1440 pts/18 T 01:30 0:00 bash killable-shell.sh sleep 100
niklas 31569 0.0 0.0 14404 616 pts/18 T 01:30 0:00 sleep 100
niklas 31605 0.0 0.0 18956 936 pts/18 S+ 01:30 0:00 grep --color=auto sleep
$ bg
[1] + 31568 continued bash killable-shell.sh sleep 100
$ kill 31568
Caught SIGTERM, sending SIGTERM to process group
[1] + 31568 terminated bash killable-shell.sh sleep 100
$ ps aux | grep "sleep"
niklas 31717 0.0 0.0 18956 936 pts/18 S+ 01:31 0:00 grep --color=auto sleep
কেবলমাত্র বৈচিত্র্যের জন্য আমি https://stackoverflow.com/a/2173421/102484 এর ভিন্নতা পোস্ট করব , কারণ এই সমাধানটি আমার পরিবেশে "সমাপ্ত" বার্তা নিয়ে যায়:
trap 'test -z "$intrap" && export intrap=1 && kill -- -$$' SIGINT SIGTERM EXIT