একমাত্র প্রধান পার্থক্য হ'ল কোনও স্ক্রিপ্ট সসোর্সিং এবং কার্যকর করা। source foo.sh
এটি উত্স করবে এবং আপনার প্রদর্শিত সমস্ত উদাহরণ কার্যকর করছে। আরো বিস্তারিত:
./file.sh
এটি file.sh
বর্তমান ডিরেক্টরিতে ( ./
) নামের একটি স্ক্রিপ্ট কার্যকর করবে । সাধারণত আপনি যখন রান করবেন command
তখন শেলটি আপনার $PATH
এক্সিকিউটেবল ফাইলের ডিরেক্টরিতে ডিরেক্টরিগুলি অনুসন্ধান করবে command
। আপনি যদি একটি পুরো পথ দেন, যেমন /usr/bin/command
বা ./command
, তবে এটি $PATH
অগ্রাহ্য করা হয় এবং সেই নির্দিষ্ট ফাইলটি কার্যকর করা হয়।
../file.sh
এটি মূলত এটির ./file.sh
জন্য বর্তমান ডিরেক্টরিটি অনুসন্ধান করার পরিবর্তে file.sh
এটি প্যারেন্ট ডিরেক্টরিতে ( ../
) সন্ধান করছে।
sh file.sh
এটি সমান sh ./file.sh
, এটি উপরে হিসাবে file.sh
বর্তমান ডিরেক্টরিতে স্ক্রিপ্ট চালিত হবে । পার্থক্যটি হ'ল আপনি sh
শেল দিয়ে এটি স্পষ্টভাবে চালাচ্ছেন । উবুন্টু সিস্টেমে, এটি dash
এবং নাও bash
। সাধারণত, স্ক্রিপ্টগুলিতে একটি শেবাং লাইন থাকে যা সেই প্রোগ্রামটি দেয় যা সে হিসাবে চালানো উচিত। তাদের সাথে অন্যকে কল করা ওভাররাইড করে। উদাহরণ স্বরূপ:
$ cat foo.sh
#!/bin/bash
## The above is the shebang line, it points to bash
ps h -p $$ -o args='' | cut -f1 -d' ' ## This will print the name of the shell
এই স্ক্রিপ্টটি চালানোর জন্য ব্যবহৃত শেলের নামটি কেবল মুদ্রণ করবে। আসুন দেখি কীভাবে ফিরে আসে যখন বিভিন্ন উপায়ে ডাকা হয়:
$ bash foo.sh
bash
$ sh foo.sh
sh
$ zsh foo.sh
zsh
সুতরাং, সাথে কোনও স্ক্রিপ্ট কল করার সাথে সাথে shell script
শেবাং লাইনটি (যদি উপস্থিত থাকে) ওভাররাইড হয়ে যায় এবং আপনি যা শেল বলুন তত স্ক্রিপ্টটি চালান।
source file.sh
অথবা . file.sh
এটিকে বলা হয়, আশ্চর্যজনকভাবে স্ক্রিপ্টের উত্সাহে যথেষ্ট । কীওয়ার্ডটি source
শেল বিল্টিন .
কমান্ডের একটি উপনাম । এটি বর্তমান শেলের মধ্যে স্ক্রিপ্টটি কার্যকর করার একটি উপায়। সাধারণত, যখন কোনও স্ক্রিপ্ট কার্যকর হয়, এটি নিজের শেলের মধ্যে চালিত হয় যা বর্তমানের চেয়ে আলাদা। বর্ণনা করা:
$ cat foo.sh
#!/bin/bash
foo="Script"
echo "Foo (script) is $foo"
এখন, আমি যদি foo
প্যারেন্ট শেলটিতে ভেরিয়েবলটি সেট করে এবং পরে স্ক্রিপ্টটি চালিত করি তবে স্ক্রিপ্টটি আলাদা মান প্রিন্ট করবে foo
(কারণ এটি স্ক্রিপ্টের মধ্যেও সেট করা আছে) তবে foo
প্যারেন্ট শেলের মান অপরিবর্তিত থাকবে:
$ foo="Parent"
$ bash foo.sh
Foo (script) is Script ## This is the value from the script's shell
$ echo "$foo"
Parent ## The value in the parent shell is unchanged
যাইহোক, আমি যদি স্ক্রিপ্টটি সম্পাদন করার পরিবর্তে উত্স করি তবে এটি একই শেলটিতে চালিত হবে সুতরাং foo
পিতামাতার মানটির পরিবর্তন হবে:
$ source ./foo.sh
Foo (script) is Script ## The script's foo
$ echo "$foo"
Script ## Because the script was sourced,
## the value in the parent shell has changed
সুতরাং, সোর্সিং এমন কয়েকটি ক্ষেত্রে ব্যবহৃত হয় যেখানে আপনি যে স্কেলটি চালাচ্ছেন তার প্রভাব ফেলতে আপনি কোনও স্ক্রিপ্ট চান। এটি সাধারণত শেল ভেরিয়েবলগুলি সংজ্ঞায়িত করতে এবং স্ক্রিপ্ট শেষ হওয়ার পরে এগুলি উপলব্ধ করার জন্য ব্যবহৃত হয়।
এই সমস্ত বিষয় মাথায় রেখে, আপনি পৃথক উত্তর পাওয়ার কারণটি প্রথমত: আপনার লিপিটি যা মনে করে তা তা করে না। এটি bash
আউটপুটে প্রদর্শিত হবে এমন সংখ্যা গণনা করে ps
। এটি ওপেন টার্মিনালের সংখ্যা নয় , এটি চলমান শেলগুলির সংখ্যা (আসলে, এটি এমনকি এটি নয়, তবে এটি অন্য একটি আলোচনা)। স্পষ্ট করার জন্য, আমি আপনার স্ক্রিপ্টটি এটিকে কিছুটা সহজ করেছি:
#!/bin/bash
logname=terdon
not=`ps -au$logname | grep -c bash`
echo "The number of shells opened by $logname is $not"
এবং এটি কেবল একটি একক টার্মিনাল খোলা দিয়ে বিভিন্ন উপায়ে চালান:
সরাসরি প্রবর্তন ./foo.sh
,।
$ ./foo.sh
The number of shells opened by terdon is 1
এখানে আপনি শেবাং লাইন ব্যবহার করছেন। এর অর্থ হ'ল স্ক্রিপ্টটি সেখানে যা কিছু সেট করা আছে তার দ্বারা সরাসরি সম্পাদন করা হয়। এটি স্ক্রিপ্টটির আউটপুটে প্রদর্শিত হয় এমনভাবে প্রভাবিত করে ps
। তালিকাভুক্ত হওয়ার পরিবর্তে bash foo.sh
এটি কেবলমাত্র প্রদর্শিত হবে foo.sh
যার অর্থ এটি grep
আপনাকে মিস করবে। আসলে 3 টি বাশ উদাহরণ রয়েছে: প্যারেন্ট প্রসেস, বাশ স্ক্রিপ্টটি চালায় এবং অন্য একটি যা ps
কমান্ডটি চালায় । এটি সর্বশেষ গুরুত্বপূর্ণ, কমান্ড প্রতিস্থাপন ( `command`
বা $(command)
) সহ একটি কমান্ড চালু করার ফলে প্যারেন্ট শেলের একটি অনুলিপি চালু হয় এবং এটি কমান্ডটি চালায়। এখানে, তবে ps
এর কোনওটিই তার আউটপুটটি দেখায় of
সুস্পষ্ট (বাশ) শেল দিয়ে সরাসরি প্রবর্তন
$ bash foo.sh
The number of shells opened by terdon is 3
এখানে, আপনি যেহেতু চলছেন bash foo.sh
, এর ফলাফল আউটপুট ps
প্রদর্শন করবে bash foo.sh
এবং গণনা করা হবে। সুতরাং, এখানে আমাদের প্যারেন্ট প্রক্রিয়া রয়েছে, bash
স্ক্রিপ্টটি চালানো এবং ক্লোন করা শেল (চলমান ps
) সমস্ত দেখানো হয়েছে কারণ এখন ps
তাদের প্রতিটি প্রদর্শন করা হবে কারণ আপনার আদেশটি শব্দটি অন্তর্ভুক্ত করবে bash
।
একটি ভিন্ন শেল ( sh
) দিয়ে সরাসরি চালু করা হচ্ছে
$ sh foo.sh
The number of shells opened by terdon is 1
এটি ভিন্ন কারণ আপনি স্ক্রিপ্টটি চালাচ্ছেন sh
এবং না bash
। অতএব, একমাত্র bash
উদাহরণটি প্যারেন্ট শেল যেখানে আপনি আপনার স্ক্রিপ্ট চালু করেছিলেন launched উপরে উল্লিখিত অন্যান্য সমস্ত শেলগুলি sh
পরিবর্তে চালিত হচ্ছে ।
সোর্সিং (হয় .
বা source
একই জিনিস দ্বারা)
$ . ./foo.sh
The number of shells opened by terdon is 2
আমি উপরে ব্যাখ্যা হিসাবে, একটি স্ক্রিপ্ট উত্সাহিত এটি পিতামাতার প্রক্রিয়া হিসাবে একই শেল চালিত কারণ। যাইহোক, ps
কমান্ডটি চালু করতে একটি পৃথক সাবશેল শুরু করা হয়েছে এবং এটি মোট দুটি করে নিয়ে আসে।
চূড়ান্ত নোট হিসাবে, চলমান প্রক্রিয়াগুলি গণনা করার সঠিক উপায়টি পার্স করা ps
নয় তবে ব্যবহার pgrep
। আপনি কেবল চালনা করলে এই সমস্ত সমস্যা এড়ানো যেত
pgrep -cu terdon bash
সুতরাং, আপনার স্ক্রিপ্টের একটি কার্যকারী সংস্করণ যা সর্বদা সঠিক সংখ্যা মুদ্রণ করে তা হ'ল (কমান্ড প্রতিস্থাপনের অনুপস্থিতিতে দ্রষ্টব্য):
#!/usr/bin/env bash
user="terdon"
printf "Open shells:"
pgrep -cu "$user" bash
উত্সাহিত হওয়ার পরে অন্যান্য সমস্ত পদ্ধতির জন্য এটি 1 এ ফিরে আসবে এবং 2 (কারণ স্ক্রিপ্টটি চালানোর জন্য একটি নতুন বাশ চালু করা হবে)। sh
শিশু প্রক্রিয়া যেহেতু চালু না হওয়ার পরে এটি চালু হবে তখনও এটি 1 এ ফিরে আসবে bash
।