আমি কীভাবে সনাক্ত করতে পারি যদি আমি সাবসিতে আছি?


24

exitনিজেকে টার্মিনাল থেকে বেরিয়ে আসার জন্য আমি বিল্টিনের কার্যকারিতাটি প্রতিস্থাপন করতে একটি ফাংশন লেখার চেষ্টা করছি ।

আমি SHLVLপরিবেশের পরিবর্তনশীলটি ব্যবহার করার চেষ্টা করেছি তবে সাব-শেলের মধ্যে এটি পরিবর্তন হবে বলে মনে হচ্ছে না:

$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2

আমার কাজটি নিম্নরূপ:

exit () {
    if [[ $SHLVL -eq 1 ]]; then
        printf '%s\n' "Nice try!" >&2
    else
        command exit
    fi
}

এটি আমাকে exitসাব-শেলগুলির মধ্যে ব্যবহারের অনুমতি দিবে না যদিও:

$ exit
Nice try!
$ (exit)
Nice try!

আমি সাবসিলে থাকি কি না তা সনাক্ত করার জন্য একটি ভাল পদ্ধতি কী?



1
তার কারণ হল এই । $ এসএইচএলভিএল হ'ল 1 কারণ আপনি এখনও শেল স্তর 1 এ রয়েছেন যদিও ইকো $ SHLVL কমান্ডটি "সাবসিলে" চালিত হচ্ছে। এই পোস্ট অনুসারে, প্রথম বন্ধনীর সাথে তৈরি সাবসেলগুলি (...)পিতামাতার প্রক্রিয়ার সমস্ত বৈশিষ্ট্য উত্তরাধিকার সূত্রে প্রাপ্ত হয়। প্রদত্ত উত্তরগুলি আপনার শেল স্তর নির্ধারণের জন্য আরও দৃ more় সমাধান।
কেমোটেপ


5
@ মোসভি আমার কাছে মনে হচ্ছে এটি একটি আলাদা প্রশ্ন is উদাহরণস্বরূপ BASH_SUBSHELLউত্তর (বিতর্কিত হলেও) প্রয়োগ করা হবে না।
স্পারহাক

2
এইচএনকিউতে শিরোনাম দেখে মনে হয়েছিল এটি একটি কোয়ান্টাম মেকানিক্স প্রশ্ন ...
মেহেরদাবাদ

উত্তর:


43

ব্যাশ, আপনি তুলনা করতে পারবেন $BASHPIDকরার$$

$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$   if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell

আপনি যদি ব্যাশে না থাকেন তবে সাব-শেলের $$ক্ষেত্রে একই থাকা উচিত, তাই আপনার আসল প্রক্রিয়া আইডি পাওয়ার জন্য অন্য কোনও উপায়ের দরকার পড়ে।

আপনার আসল পিড পাওয়ার এক উপায় sh -c 'echo $PPID'। যদি আপনি কেবল ( … )এটি একটি সমতলতে রাখেন তবে এটি প্রদর্শিত না হতে পারে, কারণ আপনার শেলটি কাঁটাচামচ অপসারণ করেছে। ( : ; sh -c 'echo $PPID'; : )সাবস্কেলটি অপ্টিমাইজ করা খুব জটিল বলে মনে করার জন্য অতিরিক্ত নো-অপ্ট কমান্ড ব্যবহার করে দেখুন। সেই পদ্ধতির জন্য স্ট্যাক ওভারফ্লোতে ক্রেডিট জন 1024 এ যায় ।


আপনি এটি পরিবর্তন করতে চাইতে পারেন  (sh -c 'echo $PPID'; : )- জন 1024 এর উত্তর সম্পর্কে আমার মন্তব্য দেখুন ।
জি-ম্যান 21

@ জি-ম্যান ওয়েল, এটি কেবল এটি পরীক্ষা করার জন্য ছিল (যেহেতু প্রকৃত ব্যবহারের ক্ষেত্রে এটি আরও জটিল কিছু হতে পারে) ... তবে হ্যাঁ, পরীক্ষাগুলি সমস্ত শেলগুলিতে কাজ করা ভাল would সুতরাং আমি এর আগে এবং পরে উভয়ই কোনও অনি পছন্দ করে রেখেছি, আশা করি এটি সবকিছু পরিচালনা করবে।
ডারোবার্ট

38

কীভাবে BASH_SUBSHELL?

BASH_SUBSHELL
      প্রতিটি পরিবেশে বা সাব- শেল পরিবেশের মধ্যে শেল যখন পরিবেশে
      চালানো শুরু করে তখন একটির দ্বারা বর্ধিত । প্রাথমিক মান 0 হয়।

$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1

16
এটি ইনসেপশন মুভিতে একটি সুবিধাজনক কমান্ড হত।
এরিক ডুমিনিল

ইনসেপশন এটা সম্ভবত $ SHLVL এর
বৃদ্ধা ধরা

19

[এটি একটি মন্তব্য হওয়া উচিত ছিল, তবে আমার মন্তব্যগুলি মডারেটরদের দ্বারা মোছার ঝোঁক রয়েছে, তাই এটি একটি উত্তর হিসাবে থাকবে যে আমি মুছে ফেলা হলেও এটি একটি রেফারেন্স হিসাবে ব্যবহার করতে পারি]]

ব্যবহার BASH_SUBSHELLসম্পূর্ণ অবিশ্বাস্য কারণ এটি কয়েকটি সাবশেলে কেবল 1 তে সেট করা থাকে , সমস্ত সাব-শেলের ক্ষেত্রে নয়।

$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0

দাবি করেন যে subprocess একটি পাইপলাইন কমান্ড চালানোর একটা নয় আগে সত্যিই বাস্তব subshell, এই বিবেচনা man bashস্নিপেট:

পাইপলাইনের প্রতিটি কমান্ড পৃথক প্রক্রিয়া হিসাবে (যেমন, একটি সাবসিলে) চালিত হয়।

এবং ব্যবহারিক প্রভাব - এটি কোনও স্ক্রিপ্ট খণ্ডটি একটি সাবপ্রসেস চালিত হয় বা যা অপরিহার্য, কোনও পরিভাষা নমনীয় নয়।

এই প্রশ্নের উত্তরে ইতিমধ্যে ব্যাখ্যা করা হয়েছে এমন একমাত্র সমাধান হ'ল $BASHPIDসমান $$বা, বহনযোগ্য তবে খুব কম দক্ষ কিনা তা পরীক্ষা করা :

if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
    echo you\'re in a subshell
fi

11
নীট: BASH_SUBSHELLবেশ নির্ভরযোগ্যভাবে সেট করা হয়েছে তবে সঠিকভাবে এর মান পাওয়া যদি হয় তবে তা নিখুঁত। দস্তাবেজগুলি কী বলেছে তা নোট করুন : " শেল যখন সেই পরিবেশে শেলটি কার্যকর করা শুরু করে তখন প্রতিটি সাবহেল বা সাবহেল পরিবেশের মধ্যে একটি করে বাড়ানো" "আমি মনে করি পাইপের উদাহরণে, ভেরিয়েবলটি প্রসারিত হওয়ার পরে বাশ এখনও সেই সাবশেলে সম্পাদন শুরু করেনি। আপনি এর echo $BASH_VERSIONসাথে তুলনা করতে পারেনdeclare -p BASH_VERSION
শেষেরটি

6
এমনকি বলুন, eval 'echo $BASH_SUBSHELL $BASHPID' | cat1 এর জন্য আউটপুট দেবে BASH_SUBSHELL, কারণ কার্যকরকরণ শুরু হওয়ার পরে চলকটি প্রসারিত হয়।
মুড়ু

4
এই সমস্ত যুক্তিগুলি প্রক্রিয়া ও কমান্ডের প্রতিস্থাপন, বিজি প্রসেসের ক্ষেত্রেও প্রয়োগ করা উচিত, তবুও এটি কেবল পাইপলাইনগুলি পৃথক different কোডটি দেখলে , অগ্রগতির পাইপলাইনগুলির ক্ষেত্রে বর্ধিতকরণকে subshell_levelসত্যই পিছিয়ে দেওয়া হয়েছে , যার সম্ভবত কোনও কারণ রয়েছে তবে আমি যা তৈরি করতে পারছি না ;-)
মশাবি

2
তুমি ঠিক বলছো. মনে হয় চেট সুস্পষ্টভাবে সেভাবে এর উদ্দেশ্য করে। list.gnu.org/archive/html/bug-bash/2015-06/msg00050.html : "BASH_SUBSHELL পরিমাপ (...) সাবস্কেল, পাইপলাইন উপাদান নয়" " list.gnu.org/archive/html/bug-bash/2015-06/msg00054.html : "আমি এই স্থিতিটি নথিভুক্ত করব বা` সাবশেল "এর সংজ্ঞাটি প্রসারিত করব should BASH_SUBSHELL প্রতিফলিত করে কিনা সে সম্পর্কে আমি ভাবতে চলেছি। "
মুড়ু

2
@ জো আপনি ভুল করছেন, প্রসারণটি পৃথক প্রক্রিয়াতেও ঘটে, দয়া করে উপরের এই আলোচনার লিঙ্কগুলি এবং উদাহরণগুলি পড়ুন; বা শুধু সাথে চেষ্টা করুন echo $$ $BASHPID $BASH_SUBSHELL | cat
মশবী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.