"সোর্স file.sh", "./file.sh", "sh file.sh", "ব্যবহার করে শেল স্ক্রিপ্টগুলি কার্যকর করার মধ্যে পার্থক্যগুলি কী। ./file.sh "?


13

কোডটি একবার দেখুন:

#!/bin/bash
read -p "Eneter 1 for UID and 2 for LOGNAME" choice
if [ $choice -eq 1 ]
then
        read -p "Enter UID:  " uid
        logname=`cat /etc/passwd | grep $uid | cut -f1 -d:`
else
        read -p "Enter Logname:  " logname
fi
not=`ps -au$logname | grep -c bash`
echo  "The number of terminals opened by $logname are $not"

এই কোডটি একই পিসিতে কোনও ব্যবহারকারী দ্বারা খোলা টার্মিনালগুলির সংখ্যা জানতে ব্যবহৃত হয়। এখন দুটি ব্যবহারকারী লগইন করেছেন, এক্স এবং y বলুন। আমি বর্তমানে y হিসাবে লগ ইন করেছি এবং এক্স এক্সটিতে 3 টি টার্মিনাল খোলা আছে। যদি আমি এই কোডটি y এর মধ্যে বিভিন্নভাবে ব্যবহার করে উপরে বর্ণিত ফলাফলগুলি কার্যকর করি:

$ ./file.sh
The number of terminals opened by x are 3

$ bash file.sh
The number of terminals opened by x are 5

$ sh file.sh
The number of terminals opened by x are 3

$ source file.sh
The number of terminals opened by x are 4

$ . ./file.sh
The number of terminals opened by x are 4

দ্রষ্টব্য: আমি এই সমস্ত এক্সিকিউটেবলের কাছে 1 এবং uid 1000 পেরিয়েছি।

এখন আপনি দয়া করে এই সমস্ত মধ্যে পার্থক্য ব্যাখ্যা করতে পারেন?


পার্থক্যটি হ'ল শেলটি কার্যকর হয়। sh বাশ নয়
j0h

2
দুটি শেষ মৃত্যুদণ্ড কার্যকরও একই কারণ আপনি একই প্রসঙ্গে মৃত্যুদণ্ড কার্যকর করছেন। আরও এখানে
জাকা ইলাব

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

@ রমনারেডি অন্যান্য ব্যবহারকারী হয়ত স্ক্রিপ্ট চালিয়েছেন বা একটি নতুন ট্যাব শুরু করেছেন। কে জানে?
মুড়ু

উত্তর:


21

একমাত্র প্রধান পার্থক্য হ'ল কোনও স্ক্রিপ্ট সসোর্সিং এবং কার্যকর করা। source foo.shএটি উত্স করবে এবং আপনার প্রদর্শিত সমস্ত উদাহরণ কার্যকর করছে। আরো বিস্তারিত:

  1. ./file.sh

    এটি file.shবর্তমান ডিরেক্টরিতে ( ./) নামের একটি স্ক্রিপ্ট কার্যকর করবে । সাধারণত আপনি যখন রান করবেন commandতখন শেলটি আপনার $PATHএক্সিকিউটেবল ফাইলের ডিরেক্টরিতে ডিরেক্টরিগুলি অনুসন্ধান করবে command। আপনি যদি একটি পুরো পথ দেন, যেমন /usr/bin/commandবা ./command, তবে এটি $PATHঅগ্রাহ্য করা হয় এবং সেই নির্দিষ্ট ফাইলটি কার্যকর করা হয়।

  2. ../file.sh

    এটি মূলত এটির ./file.shজন্য বর্তমান ডিরেক্টরিটি অনুসন্ধান করার পরিবর্তে file.shএটি প্যারেন্ট ডিরেক্টরিতে ( ../) সন্ধান করছে।

  3. 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শেবাং লাইনটি (যদি উপস্থিত থাকে) ওভাররাইড হয়ে যায় এবং আপনি যা শেল বলুন তত স্ক্রিপ্টটি চালান।

  4. 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"

এবং এটি কেবল একটি একক টার্মিনাল খোলা দিয়ে বিভিন্ন উপায়ে চালান:

  1. সরাসরি প্রবর্তন ./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

  2. সুস্পষ্ট (বাশ) শেল দিয়ে সরাসরি প্রবর্তন

    $ bash foo.sh 
    The number of shells opened by terdon is 3
    

    এখানে, আপনি যেহেতু চলছেন bash foo.sh, এর ফলাফল আউটপুট psপ্রদর্শন করবে bash foo.shএবং গণনা করা হবে। সুতরাং, এখানে আমাদের প্যারেন্ট প্রক্রিয়া রয়েছে, bashস্ক্রিপ্টটি চালানো এবং ক্লোন করা শেল (চলমান ps) সমস্ত দেখানো হয়েছে কারণ এখন psতাদের প্রতিটি প্রদর্শন করা হবে কারণ আপনার আদেশটি শব্দটি অন্তর্ভুক্ত করবে bash

  3. একটি ভিন্ন শেল ( sh) দিয়ে সরাসরি চালু করা হচ্ছে

    $ sh foo.sh
    The number of shells opened by terdon is 1
    

    এটি ভিন্ন কারণ আপনি স্ক্রিপ্টটি চালাচ্ছেন shএবং না bash। অতএব, একমাত্র bashউদাহরণটি প্যারেন্ট শেল যেখানে আপনি আপনার স্ক্রিপ্ট চালু করেছিলেন launched উপরে উল্লিখিত অন্যান্য সমস্ত শেলগুলি shপরিবর্তে চালিত হচ্ছে ।

  4. সোর্সিং (হয় .বা 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


যখন আপনি বলছেন কমান্ড প্রতিস্থাপন প্যারেন্ট শেলের একটি অনুলিপি চালু করে, আপনি যখন / / foo.sh দিয়ে স্ক্রিপ্টটি চালাবেন তখন এই অনুলিপি কীভাবে একটি সাব-শেল থেকে আলাদা হয়?
দিদিয়ের এ।

এবং আপনি যখন কমান্ড সাবস্টিটিউশন ছাড়াই পিগ্রেপ চালান, আমি ধরে নিই যে এটি একই শেল থেকে স্ক্রিপ্টটি চালাচ্ছে? সোর্সিং এর মতো?
দিদিয়ের এ।

@ ডিডিবাস আমি নিশ্চিত না আপনি কী বলতে চাইছেন। কমান্ড প্রতিস্থাপন একটি সাব-শেলের মধ্যে চলমান; ./foo.shএকটি নতুন শেল চালায় যা পিতামাতার অনুলিপি নয়। উদাহরণস্বরূপ, আপনি foo="bar"যদি আপনার টার্মিনালে সেট করেন এবং তারপরে একটি স্ক্রিপ্ট চালায় যা echo $fooআপনি কার্যকর করেন তবে আপনি একটি খালি লাইন পাবেন যেহেতু স্ক্রিপ্টের শেলটি ভেরিয়েবলের মান উত্তরাধিকার সূত্রে প্রাপ্ত হয় নি। pgrepএকটি পৃথক বাইনারি, এবং হ্যাঁ এটি আপনি চালিত স্ক্রিপ্ট দ্বারা চালিত হয়।
টেরডন

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