একটি সাব-শেল থেকে শেল স্ক্রিপ্ট প্রস্থান করুন


30

এই স্নিপেট বিবেচনা করুন:

stop () {
    echo "${1}" 1>&2
    exit 1
}

func () {
    if false; then
        echo "foo"
    else
        stop "something went wrong"
    fi
}

সাধারণত যখন funcডাকা হয় তখন এটি স্ক্রিপ্টটি শেষ করে দেবে, যা উদ্দেশ্যমূলক আচরণ। তবে এটি যদি একটি সাব-শেলতে কার্যকর করা হয় তবে যেমন

result=`func`

এটি স্ক্রিপ্ট থেকে প্রস্থান করবে না। এর অর্থ হ'ল কলিং কোডটি প্রতিবার ফাংশনের প্রস্থান স্থিতি পরীক্ষা করতে হয়। এই সমস্যা এড়ানোর জন্য একটি উপায় আছে কি? এটি কি set -eজন্য হয়?


1
আমি একটি ফাংশন "স্টপ" চাই যা স্টেডারে একটি বার্তা প্রিন্ট করে এবং স্ক্রিপ্টটি থামায়, তবে থামবে না যে থামানো ফাংশনটি একটি সাব-শেলের মধ্যে কার্যকর করা হবে, উদাহরণস্বরূপ
আর্নেস্ট এসি

2
অবশ্যই, কারণ এটি সাবসেল থেকে প্রস্থান করে বর্তমানটি নয়। কেবলমাত্র ফাংশন সরাসরি কল: func

1
আমি এটিকে সরাসরি কল করতে পারি না কারণ এটি একটি স্ট্রিং ফিরিয়ে দেয় যা একটি ভেরিয়েবলে সংরক্ষণ করতে হবে
আর্নেস্ট এসি

1
@ আর্নেস্ট্যাক দয়া করে মূল প্রশ্নের সমস্ত বিবরণ সরবরাহ করুন। উপরের ফাংশনটি কোনও স্ট্রিং দেয় না।

1
@htor আমি উদাহরণটি পরিবর্তন করেছি
আর্নেস্ট এসি

উত্তর:


10

কল করার আগে আপনি মূল শেলটি ( ) মেরে ফেলতে পারেন এবং সম্ভবত এটি কাজ করবে। কিন্তু:kill $$exit

  • এটা আমার কাছে বরং কুৎসিত বলে মনে হচ্ছে
  • এটি যদি আপনার সেখানে দ্বিতীয় সাবশেল থাকে তবে এটি ভেঙে যাবে, অর্থাৎ সাবসেলের অভ্যন্তরে একটি সাব-শেল ব্যবহার করুন।

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


5
ধন্যবাদ। আমি বরং পাইথনে স্যুইচ করব।
আর্নেস্ট এসি

2
আমি যেমন লিখছি, এটি ২০১৮ সাল someone কাউকে "পার্লে স্যুইচ করুন" বলতে বলা হাস্যকর। বিতর্কিত হওয়ার জন্য দুঃখিত, তবে আপনি কি কোবুলে স্যুইচ করতে 'সি' নিয়ে হতাশ কাউকে বলবেন, যা আইএমও সমতুল্য? আর্নেস্ট যেমন উল্লেখ করেছেন, পাইথন আরও ভাল পছন্দ। আমার পছন্দ হবে রুবি। যেভাবেই হোক, পার্ল ছাড়া আর কিছু নয়।
গ্রাহাম নিকোলস

38

আপনি সিদ্ধান্ত নিতে পারেন যে প্রস্থান স্থিতির জন্য উদাহরণস্বরূপ 77 means এর অর্থ সাবলেকের যে কোনও স্তর থেকে প্রস্থান করুন এবং করুন

set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR

(
  echo here
  (
    echo there
    (
      exit 12 # not 77, exit only this subshell
    )
    echo ici
    exit 77 # exit all subshells
  )
  echo not here
)
echo not here either

set -EERRফাঁদগুলির সাথে সংমিশ্রণটি set -eএটির উন্নত সংস্করণের মতো যা আপনাকে নিজের ত্রুটি পরিচালনার সংজ্ঞা দিতে দেয়।

জেডএস-এ, ইআরআর ফাঁদগুলি স্বয়ংক্রিয়ভাবে উত্তরাধিকার সূত্রে প্রাপ্ত হয়, সুতরাং আপনার প্রয়োজন নেই set -E, আপনি ফাঁদগুলি TRAPERR()ফাংশন হিসাবে সংজ্ঞায়িত করতে এবং তাদের মাধ্যমে সংশোধন করতে $functions[TRAPERR]পারেন,functions[TRAPERR]="echo was here; $functions[TRAPERR]"


1
আকর্ষণীয় সমাধান! স্পষ্টতই তুলনায় আরও মার্জিত kill $$

3
একটি বিষয় লক্ষ্য রাখবেন, এই ফাঁদটি ইন্টারপোলটেড কমান্ডগুলি পরিচালনা করবে না, যেমন echo "$(exit 77)"; স্ক্রিপ্টটি echo ""
এমনভাবে চলবে

Interresting! (বেশ বয়স্ক) বাশ-এর ​​কোন ভাগ্য নেই যা -ই নেই? সম্ভবত আমাদের কোনও ইউএসআইএল সিগন্যালের ফাঁদ সংজ্ঞায়িত করতে হবে এবং সেই সংকেতটিতে একটি কিল ব্যবহার করতে হবে? আমিও কিছু পুনর্নির্মাণ করব ...
অলিভিয়ার ডুলাক

উপ-শেল ফাঁদে থাকা অবস্থায়, 77 এর পরিবর্তে 1 ফেরত দেওয়ার জন্য কীভাবে জানবেন?
সিলিং

7

এর বিকল্প হিসাবে kill $$, আপনি চেষ্টাও করতে পারেন kill 0, এটি নেস্টেড সাব-শেলগুলির ক্ষেত্রে কাজ করবে (সমস্ত কলার এবং সাইড প্রসেসটি সংকেত গ্রহণ করবে) ... তবে এটি এখনও নিষ্ঠুর এবং কুৎসিত।


2
এই কিল প্রক্রিয়া আইডি 0 হবে না?
আর্নেস্ট এসি

5
এটি পুরো প্রক্রিয়া গোষ্ঠীকে হত্যা করবে। আপনি চান না এমন জিনিসগুলিতে আপনি আঘাত করতে পারেন (উদাহরণস্বরূপ আপনি ব্যাকগ্রাউন্ডে কিছু জিনিস শুরু করেছেন)।
ডারোবার্ট

2
@ আর্নেস্ট্যাক দেখুন কিল (২) ম্যানপেজ, পিড ≤0 এর বিশেষ অর্থ রয়েছে।
ডার্বার্ট

0

এটা চেষ্টা কর ...

stop () {
    echo "${1}" 1>&2
    exit 1
}

func () {
    if $1; then
        echo "foo"
    else
        stop "something went wrong"
    fi
}

echo "shell..."
func $1

echo "subshell..."
result=`func $1`

echo "shell..."
echo "result=$result"

আমি যে ফলাফল পেয়েছি তা হ'ল ...

# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong

নোট

  • ifপরীক্ষার অনুমতি দেওয়ার জন্য প্যারামিটারাইজড trueবা false(২ রান দেখুন)
  • যখন ifপরীক্ষা হয় false, আমরা কখনই সাব-শেল পৌঁছায় না।

এটি ব্যবহারকারীর পোস্টিংয়ের মূল ধারণার সাথে খুব মিল এবং বলেছে যে এটি কাজ করে না। আমি মনে করি না এটি সাবসেলের ক্ষেত্রে কাজ করে। আপনার পরীক্ষা "শেল" কেসের পরে মিথ্যা প্রস্থান করে এবং কখনই "সাবশেল" টেস্ট কেসে যায় না। আমি বিশ্বাস করি এটি সেই ক্ষেত্রে ব্যর্থ হবে যেহেতু সাবশেলটি "প্রস্থান 1" কলটি থেকে বেরিয়ে আসবে কিন্তু ত্রুটিটি বাইরের শেলটিতে প্রচার করবে না।
আটকে

0

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

বৃহত্তর স্ক্রিপ্টে বিভিন্ন ব্যাশ কোডের বিটগুলি অন্তর্ভুক্ত করার চেষ্টা করার সময় এটি জটিল হতে পারে। এক ভাগ বাশ নিজেই ঠিকঠাক কাজ করতে পারে, কিন্তু যখন ইরেরেক্সিটের (বা এররেক্সিট ছাড়াই) মৃত্যুদন্ড কার্যকর করা হয়, তখন অপ্রত্যাশিতভাবে আচরণ করা।

[192.168.13.16 (f0f5e19e) ~ 22:58:22] # বাশ -o এরেক্সিট / টিএমপি / ফু
কিছু ভুল হয়েছে
[192.168.13.16 (f0f5e19e) ~ 22:58:31] # বাশ / টিএমপি / ফু
কিছু ভুল হয়েছে
তবে আমরা যাইহোক এখানে পেয়েছি
[192.168.13.16 (f0f5e19e) ~ 22:58:37] # বিড়াল / টিএমপি / ফু
#! / বিন / ব্যাশ
বন্ধ () {
    প্রতিধ্বনি "$ {1}"
    প্রস্থান 1
}

যদি মিথ্যা; তারপর
    প্রতিধ্বনি "ফু"
আর
    (
        "কিছু ভুল হয়েছে" থামান
    )
    প্রতিধ্বনি "তবে আমরা যাইহোক এখানে এসেছি"
ফাই
[192.168.13.16 (f0f5e19e) ~ 22:58:40] #

-2

এক লাইনে প্রস্থান করার জন্য আমার উদাহরণ:

COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit

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