বাশ-এ সাবসেল চাওয়ার নিয়ম?


24

আমি সাব-শেল তৈরির জন্য বাশ বিধিটিকে ভুল বুঝেছি বলে মনে হচ্ছে। আমি ভেবেছিলাম প্রথম বন্ধনী সর্বদা একটি সাবশেল তৈরি করে যা এটি নিজস্ব প্রক্রিয়া হিসাবে চলে।

যাইহোক, এটি মনে হয় না। কোড স্নিপেট এ (নীচে) এ, দ্বিতীয় sleepকমান্ডটি পৃথক শেলটিতে চালিত হয় না ( pstreeঅন্য টার্মিনালের দ্বারা নির্ধারিত )। যাইহোক, কোড স্নিপেট বি, SECOND sleepকমান্ড নেই আলাদা শেল চালানো। স্নিপেটগুলির মধ্যে পার্থক্যটি হ'ল দ্বিতীয় স্নিপেটের প্রথম বন্ধনীর মধ্যে দুটি কমান্ড রয়েছে।

সাবস্কেলগুলি কখন তৈরি হয় তার জন্য কেউ দয়া করে নিয়মটি ব্যাখ্যা করতে পারেন?

কোড স্নিপেট এ:

sleep 5
(
sleep 5
)

কোড স্নিপেট বি:

sleep 5
(
x=1
sleep 5
)

উত্তর:


20

প্রথম বন্ধনী সর্বদা একটি সাব-শেল শুরু করে। যা ঘটছে তা হ'ল বাশ সনাক্ত করে যে sleep 5সেই সাবশেলের দ্বারা সম্পাদিত শেষ আদেশটি, সুতরাং এটি + এর execপরিবর্তে কল করে । কমান্ড একই প্রক্রিয়ায় subshell প্রতিস্থাপন করে।forkexecsleep

অন্য কথায়, বেস কেসটি হ'ল:

  1. ( … )একটি সাব-শেল তৈরি করুন। আসল প্রক্রিয়া কল forkএবং wait। সাব প্রোসেসে, যা একটি সাবশেল:
    1. sleepএকটি বাহ্যিক কমান্ড যা সাব-প্রসেসের একটি সাবপ্রসেস প্রয়োজন। সাবশেল কল forkএবং wait। সাব-প্রসেসে:
      1. সাবসুবপ্রসেস বাহ্যিক কমান্ড কার্যকর করে → exec
      2. অবশেষে কমান্ডটি সমাপ্ত হয় → exit
    2. wait সাবহেল সমাপ্ত।
  2. wait আসল প্রক্রিয়াটি সম্পূর্ণ করে।

অপ্টিমাইজেশনটি হ'ল:

  1. ( … )একটি সাব-শেল তৈরি করুন। আসল প্রক্রিয়া কল forkএবং wait। সাব-প্রসেসে, এটি কল না হওয়া পর্যন্ত এটি একটি সাবশেল exec:
    1. sleep এটি একটি বাহ্যিক আদেশ এবং এই প্রক্রিয়াটি করা শেষ কাজ thing
    2. সাবপ্রসেস বাহ্যিক কমান্ড কার্যকর করে → exec
    3. অবশেষে কমান্ডটি সমাপ্ত হয় → exit
  2. wait আসল প্রক্রিয়াটি সম্পূর্ণ করে।

কল করার পরে আপনি যখন অন্য কিছু যুক্ত করেন তখন sleepসাব-শেলটি চারপাশে রাখা দরকার, সুতরাং এই অপটিমাইজেশনটি ঘটতে পারে না।

কল করার আগে আপনি যখন অন্য কিছু যুক্ত করেন sleep, তখন অপটিমাইজেশন তৈরি করা যেতে পারে (এবং কেএসএস এটি করে) তবে ব্যাশ তা করে না (এটি এই অপটিমাইজেশনের সাথে খুব রক্ষণশীল)।


সাবস্কেল কল করে তৈরি করা হয় forkএবং কলিংয়ের মাধ্যমে শিশু প্রক্রিয়া তৈরি হয় (বাহ্যিক আদেশগুলি কার্যকর করতে)fork + exec । তবে আপনার প্রথম প্যারাটি সুপারিশ করে যে fork + execএটি সাবসেলের জন্যও ডাকা হয়। এখানে আমি কী ভুল করছি?
হ্যাক

1
@ হ্যাকস fork+ execকে সাবশেলের জন্য ডাকা হয় না, এটি বাহ্যিক কমান্ডের জন্য বলা হয়। কোনও অপ্টিমাইজেশন ছাড়াই forkসাবসেলের জন্য কল রয়েছে এবং অন্য একটি বাহ্যিক কমান্ডের জন্য। আমি আমার উত্তরে একটি প্রবাহের বিশদ বিবরণ যুক্ত করেছি।
গিলস

আপডেটের জন্য একটি টন ধন্যবাদ। এখন এটি আরও ভাল ব্যাখ্যা করে। আমি এটি থেকে অনুমান করতে পারি যে (...)(বেস ক্ষেত্রে) ক্ষেত্রে execসাবসেলের কার্য সম্পাদনের জন্য কোনও বহিরাগত আদেশ রয়েছে কিনা তার উপর নির্ভর করার জন্য কল আসতে পারে বা নাও হতে পারে, যখন কোনও বহিরাগত কমান্ড কার্যকর করার ক্ষেত্রে অবশ্যই তা করা উচিত fork + exec
7:02

আরও একটি প্রশ্ন: এই অপটিমাইজেশনটি কেবল সাব- dateশেলের জন্যই কাজ করে বা এটি শেলের মতো কমান্ডের জন্যও করা যেতে পারে ?
হ্যাক 15

@ হ্যাকস আমি প্রশ্নটি বুঝতে পারি না। এই অপ্টিমাইজেশনটি শেল প্রক্রিয়াটি শেষ কাজ হিসাবে একটি বাহ্যিক কমান্ড আহ্বান সম্পর্কে। এটি strace -f -e clone,execve,write bash -c 'date'strace -f -e clone,execve,write bash -c 'date; true'
সাবসেলগুলির মধ্যেই

4

থেকে উন্নত ব্যাশ প্রোগ্রামিং গাইড :

"সাধারণভাবে, স্ক্রিপ্টের একটি বহিরাগত কমান্ড একটি সাবপ্রসেসটি বন্ধ করে দেয়, যেখানে একজন ব্যাশ অন্তর্নির্মিত হয় না this এই কারণে, বিল্টিনগুলি আরও দ্রুত সম্পাদন করে এবং তাদের বাহ্যিক কমান্ডের সমতুল্যগুলির তুলনায় কম সিস্টেম সংস্থান ব্যবহার করে।"

এবং আরও কিছুটা নিচে:

"প্রথম বন্ধকের মধ্যে এম্বেড করা একটি কমান্ড তালিকা সাব-শেল হিসাবে চলে।"

উদাহরণ:

[root@talara test]# echo $BASHPID
10792
[root@talara test]# (echo $BASHPID)
4087
[root@talara test]# (echo $BASHPID)
4088
[root@talara test]# (echo $BASHPID)
4089

ওপিএস কোড ব্যবহার করার উদাহরণ (ছোট্ট ঘুমের সাথে কারণ আমি অধৈর্য):

echo $BASHPID

sleep 2
(
    echo $BASHPID
    sleep 2
    echo $BASHPID
)

আউটপুট:

[root@talara test]# bash sub_bash
6606
6608
6608

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

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

@ বাশফুল আমি আমার কোডটি আপনার $BASHPIDভেরিয়েবলের সাথে হ্যাক করার স্বাধীনতা নিয়েছি । দুঃখের বিষয় আপনি যেভাবে এটি করছেন তা আপনাকে বিশ্বাস করে পুরো গল্পটি দিচ্ছিল না। উত্তরে আমার যুক্ত আউটপুট দেখুন।
টিম

4

@ গিলস উত্তর একটি অতিরিক্ত নোট।

যেমন গিলস বলেছেন: The parentheses always start a subshell.

যাইহোক, এই ধরনের সাব-শেলগুলির সংখ্যার পুনরাবৃত্তি হতে পারে:

$ (echo "$BASHPID and $$"; sleep 1)
2033 and 31679
$ (echo "$BASHPID and $$"; sleep 1)
2040 and 31679
$ (echo "$BASHPID and $$"; sleep 1)
2047 and 31679

আপনি দেখতে পাচ্ছেন, $$ পুনরাবৃত্তি করে চলেছে, এবং এটি প্রত্যাশার মতো, কারণ (সঠিক man bashলাইনটি সন্ধান করতে এই আদেশটি কার্যকর করুন ):

$ LESS=+/'^ *BASHPID' man bash

BASHPID
বর্তমান ব্যাশ প্রক্রিয়াটির প্রসেস আইডিতে প্রসারিত করে। এটি circumstances নির্দিষ্ট পরিস্থিতিতে যেমন পৃথক শেলগুলির জন্য বাশকে পুনরায় আরম্ভ করার প্রয়োজন হয় না তার থেকে পৃথক হয়।

তা হ'ল: যদি শেলটি পুনরায় আরম্ভ না করা হয় তবে $$ একই।

বা এর সাথে:

$ LESS=+/'^ *Special Parameters' man bash

বিশেষ পরামিতি
$ শেলের প্রসেস আইডিতে প্রসারিত হয়। একটি () সাবশেলে এটি বর্তমান শেলের প্রসেস আইডিতে প্রসারিত হয়, সাব-শেল নয়।

এটি $$হ'ল বর্তমান শেলের আইডি (সাবসেল নয়)।


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