শিবাং কি শেলটি নির্ধারণ করে যা স্ক্রিপ্টটি চালায়?


84

এটি একটি নির্বোধ প্রশ্ন হতে পারে, তবে আমি এটি এখনও জিজ্ঞাসা করি। আমি যদি শেবাং ঘোষণা করি

#!/bin/bash 

এর শুরুতে my_shell_script.sh, তাই আমাকে সবসময় ব্যাশ ব্যবহার করে এই স্ক্রিপ্টটি চালু করতে হবে

[my@comp]$bash my_shell_script.sh

অথবা আমি যেমন ব্যবহার করতে পারি

[my@comp]$sh my_shell_script.sh

এবং আমার স্ক্রিপ্টটি শেবাং ব্যবহার করে চলমান শেলটি নির্ধারণ করে? kshশেলের সাথেও কি একই ঘটনা ঘটছে ? আমি এআইএক্স ব্যবহার করছি।


6
আপনার পক্ষ থেকে একটি সামান্য বিভ্রান্তি রয়েছে: আপনি যখন "_ কিছু_শেল কিছু_স্ক্রিপ্ট" করেন তখন এটি_সোম_শেল শুরু হয় এবং কিছু_স্ক্রিপ্টের ব্যাখ্যা দিতে বলে। সুতরাং না, আপনি যদি "sh my_shell_script.sh" করেন তবে এটি শেবাংকে ব্যাখ্যা করবে না, তবে পরিবর্তে স্ক্রিপ্টটির ব্যাখ্যা করবে। শেবাংটি ব্যবহার করতে: chmod +x my_shell_script.sh ; /path/to/my_shell_script.sh # or ./my_shell_script.sh if you happen to be in its directory
অলিভিয়ার ডুলাক

উত্তর:


117

কুঁড়েঘর #! একটি একজন মানুষের পাঠযোগ্য উদাহরণস্বরূপ হয় ম্যাজিক নম্বর বাইট স্ট্রিং গঠিত 0x23 0x21, যা দ্বারা ব্যবহৃত হয় exec()ফাংশন পরিবার কিনা তা নির্ধারণ করতে ফাইল কার্যকর করা একটি স্ক্রিপ্ট বা একটি বাইনারি হয়। যখন শেবাং উপস্থিত থাকবে, exec()পরিবর্তে শিবাংয়ের পরে নির্ধারিত এক্সিকিউটেবল চালাবে।

মনে রাখবেন এর অর্থ হ'ল আপনি যদি কমান্ড লাইনে দোভাষীকে নির্দিষ্ট করে কোনও স্ক্রিপ্ট আবেদন করেন, যেমন প্রশ্নে দেওয়া উভয় ক্ষেত্রেই করা হয়েছে, exec()কমান্ড লাইনে বর্ণিত দোভাষীকে কার্যকর করবে, এটি স্ক্রিপ্টের দিকেও তাকাবে না।

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

আচরণটি নিম্নলিখিত স্ক্রিপ্টের সাহায্যে প্রদর্শিত সহজ:

#!/bin/ksh
readlink /proc/$$/exe

ব্যাখ্যা:

  • #!/bin/kshkshদোভাষী হতে সংজ্ঞা দেয়।

  • $$ বর্তমান প্রক্রিয়াটির পিআইডি ধারণ করে।

  • /proc/pid/exe প্রক্রিয়াটির এক্সিকিউটেবলের জন্য একটি সিমিলিংক (অন্তত লিনাক্সে; এআইএক্সে, / প্রোপ / $$/object/a.out এক্সিকিউটেবলের একটি লিঙ্ক)।

  • readlink প্রতীকী লিঙ্কটির মান আউটপুট দেবে।

উদাহরণ:

উল্লেখ্য : আমি উবুন্টু, যেখানে ডিফল্ট শেল এই প্রদর্শক করছি /bin/shকরার জন্য একটি সিমবলিক লিঙ্ক হয় ড্যাশ অর্থাত /bin/dashএবং /bin/kshএকটি সিমবলিক লিঙ্ক হয় /etc/alternatives/ksh, যেটা ঘুরে ফিরে একটি সিমবলিক লিঙ্ক হয় /bin/pdksh

$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash

থমাসকে এই উত্তরের জন্য ধন্যবাদ। ভেবে আমরা স্ক্রিপ্টটি নোড.জেএস বা জাভা বা যে কোনও কিছুই থেকে শিশু প্রক্রিয়া হিসাবে চালু করি। আমরা কি "এক্সিকিউট" প্রক্রিয়া চালু করতে পারি, এবং তারপরে এক্সেল শেল স্ক্রিপ্টটি চালাবে? আমি কারণ জিজ্ঞাসা করছি আমি এই প্রশ্নের উত্তর খুঁজছি: stackoverflow.com/questions/41067872/…
আলেকজান্ডার মিলস

1
@ আলেকজান্ডারমিলস exec()এই উত্তরে উল্লিখিত একটি সিস্টেম কল, কমান্ডটি execশেল বিল্টিন, যার কারণে আপনি নোড.জেএস বা জাভা থেকে কোনও exec প্রোগ্রাম শুরু করতে পারবেন না । তবে Runtime.exec()জাভাতে উদ্বোধিত যে কোনও শেল কমান্ডটি শেষ পর্যন্ত exec()সিস্টেম কল দ্বারা প্রসেস করা হবে।
থমাস নাইম্যান

হাহ, হাঁ আমি জাভা এপিআই আপনি শুধু উল্লিখিত indeede পরিচিত, আমি ভাবছি নিম্ন স্তরের Exec ডাকা (ক উপায় নেই যদি থাকে) একরকম Node.js থেকে কল am
আলেকজান্ডার মিলস

@ আলেকজান্ডারমিলস আমি কল্পনা করব child_process.{exec(),execFile(),spawn()} সবগুলি সি exec()(মাধ্যমে process) ব্যবহার করে প্রয়োগ করা হবে ।
থমাস নাইম্যান

10

হ্যাঁ এটা করে. যাইহোক এটি একটি নির্বোধ প্রশ্ন নয়। আমার উত্তরের একটি রেফারেন্স এখানে । স্ক্রিপ্ট শুরু # দিয়ে!

  • একে শেবাং বা "ব্যাং" লাইন বলা হয়।

  • এটি ব্যাশ ইন্টারপ্রেটারের পরম পথ ছাড়া আর কিছুই নয়।

  • এটিতে একটি সংখ্যা চিহ্ন এবং একটি বিস্ময়কর বিন্দু অক্ষর (#!) থাকে, এরপরে / বিন / ব্যাশের মতো দোভাষীর পুরো পথ অনুসরণ করে।

    লিনাক্সের অধীনে সমস্ত স্ক্রিপ্টগুলি প্রথম লাইনে নির্দিষ্ট করা দোভাষী ব্যবহার করে চালিত হয় প্রায় সমস্ত বাশ স্ক্রিপ্টগুলি প্রায়শই #! / বিন / ব্যাশ দিয়ে শুরু হয় (ধরে নেওয়া যায় যে বাশ / বিনে ইনস্টল করা আছে) এটি নিশ্চিত করে যে স্ক্রিপ্ট ব্যাখ্যার জন্যও ব্যাশ ব্যবহৃত হবে যদি এটি অন্য শেলের অধীনে কার্যকর হয়। বেল ল্যাবরেটরিজে ডেনিস রিচি সংস্করণ 7 ইউনিক্স এবং 8 এর মধ্যে চালু করেছিলেন শেবাং। এরপরে এটি বার্কলে বিএসডি লাইনে যুক্ত করা হয়েছিল।

ইন্টারপ্রেটার লাইন উপেক্ষা করা (শেবাং)

যদি আপনি কোনও দোভাষী লাইনটি নির্দিষ্ট না করেন তবে ডিফল্টটি সাধারণত / বিন / শ হয়। তবে, আপনি #! / বিন / বাশ লাইন সেট করার পরামর্শ দেওয়া হচ্ছে।


3
বিস্তারিতভাবে বলতে গেলে, কার্নেল কেবল স্ট্যাটিকালি লিঙ্কযুক্ত বাইনারিগুলি কার্যকর করতে এবং অন্যের জন্য দোভাষী সম্পর্কিত তথ্য কোথায় পাবেন (বাইনারিতে একটি বিশেষ ক্ষেত্র, বা শেবাং লাইনের) কীভাবে তা আবিষ্কার করতে পারেন। সাধারণত শেল স্ক্রিপ্ট চালানো মানে শেল থেকে শেবাং লাইন অনুসরণ করা এবং তারপরে গতিশীল লিঙ্কারে শেল বাইনারিতে DT_INTERP ক্ষেত্র অনুসরণ করা।
সাইমন রিখটার

5
আরও মনে রাখবেন যে এটি শেল স্ক্রিপ্টগুলির মধ্যে সীমাবদ্ধ নয়। সমস্ত পাঠ্য ভিত্তিক স্ক্রিপ্ট ফাইল এটি ব্যবহার করে। উদাহরণস্বরূপ, #!/usr/bin/perl #!/usr/local/bin/python #!/usr/local/bin/rubyএকাধিক সিস্টেমকে সমর্থন করার জন্য ব্যবহৃত অন্য সাধারণ শেবাং এন্ট্রি #!/usr/bin/env perl #!/usr/bin/env python
হ'ল এনভিভি

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

1
@ পোলেমন কম যা পছন্দ করা হয় এবং আরও বেশি যা পাথে পৃথক হয়। প্রাথমিক শেলগুলি সমস্ত সিস্টেমে একই পথে রয়েছে। পার্ল এবং পাইথনের সর্বশেষতম সংস্করণ বিভিন্ন সিস্টেমে বিভিন্ন স্থানে ইনস্টল করা যেতে পারে তাই এনভি ব্যবহার করে একই শেবাং সর্বদা কাজ করতে দেয়, এজন্য এনভিটি শেল স্ক্রিপ্টগুলির চেয়ে পার্ল এবং পাইথন স্ক্রিপ্টগুলির সাথে বেশি ব্যবহৃত হয়।

envprogram PATH তে একটি প্রোগ্রাম সন্ধান করা হ্যাক একটি বিট। এটি নামের দ্বারা পরিবেশের পরিবর্তনগুলি সেট করে না। AT পথ বিভিন্ন ব্যবহারকারীর জন্য আলাদা ফলাফল হতে পারে। তবে এটি স্ক্রিপ্টগুলিকে এমন কোনও সিস্টেমে সংশোধন ছাড়াই চলতে সহায়তা করে যা কিছু অদ্ভুত স্থানে যুক্তিসঙ্গত পার্ল ইন্টারপ্রেটার রাখে।
জন মাহোয়াল্ড

4

execলিনাক্স কার্নেল সিস্টেম কল shebangs বুঝতে পারে ( #!) নেটিভ

আপনি যখন ব্যাশ করবেন:

./something

লিনাক্সে, execএটি পথের সাথে সিস্টেম কলকে কল করে ./something

কার্নেলের এই লাইনটি এই ফাইলটিতে পাঠানো হবে exec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

এটি ফাইলের প্রথম বাইটগুলি পড়ে এবং তাদের সাথে তুলনা করে #!

যদি তুলনাটি সত্য হয়, তবে বাকী রেখাটি লিনাক্স কার্নেল দ্বারা বিশ্লেষণ করা হয়েছে, যা প্রথম আর্গুমেন্ট হিসাবে execপাথ /usr/bin/env pythonএবং বর্তমান ফাইলের সাথে আরেকটি কল করে :

/usr/bin/env python /path/to/script.py

এবং এটি এমন কোনও স্ক্রিপ্টিং ভাষার জন্য কাজ করে যা #মন্তব্য চরিত্র হিসাবে ব্যবহার করে ।

এবং হ্যাঁ, আপনি এটি দিয়ে একটি অসীম লুপ তৈরি করতে পারেন:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

বাশ ত্রুটিটি সনাক্ত করে:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! মানুষের পাঠযোগ্য হতে পারে, তবে এটির প্রয়োজন নেই।

যদি ফাইলটি বিভিন্ন বাইট দিয়ে শুরু হয়, তবে execসিস্টেম কলটি একটি ভিন্ন হ্যান্ডলার ব্যবহার করবে। অন্যান্য গুরুত্বপূর্ণ বিল্ট-ইন হ্যান্ডলারটি ইএলএফ এক্সিকিউটেবল ফাইলগুলির জন্য: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 যা বাইটগুলি পরীক্ষা করে 7f 45 4c 46(যা মানুষের মতো হয়ে ওঠে জন্য পঠনযোগ্য .ELF)। আসুন নিশ্চিত করুন যে 4 টি প্রথম বাইট পড়ে /bin/ls, যা একটি ELF এক্সিকিউটেবল:

head -c 4 "$(which ls)" | hd 

আউটপুট:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

সুতরাং যখন কার্নেল সেগুলি বাইটগুলি দেখে, এটি ELF ফাইলটি নেয়, এটিকে সঠিকভাবে মেমরিতে রাখে এবং এটি দিয়ে একটি নতুন প্রক্রিয়া শুরু করে। আরও দেখুন: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861

অবশেষে, আপনি binfmt_miscযান্ত্রিকতার সাথে নিজের শেবাং হ্যান্ডলার যুক্ত করতে পারেন । উদাহরণস্বরূপ, আপনি ফাইলগুলির জন্য.jar একটি কাস্টম হ্যান্ডলার যুক্ত করতে পারেন । এই প্রক্রিয়াটি এমনকি ফাইল এক্সটেনশনের মাধ্যমে হ্যান্ডলারদের সমর্থন করে। আর একটি অ্যাপ্লিকেশন হ'ল কিউইএমইউ সহ স্বতন্ত্রভাবে একটি ভিন্ন স্থাপত্যের এক্সিকিউটেবলগুলি চালানো

আমি মনে করি না পসআইএক্স শেবাং সুনির্দিষ্ট করে বলেছে: https://unix.stackexchange.com/a/346214/32558 যদিও এটি যুক্তি বিভাগে এবং ফর্মটিতে "যদি এক্সিকিউটেবল স্ক্রিপ্টগুলি সিস্টেমের দ্বারা সমর্থিত হয় তবে" ঘটতে পারে".


1
./somethingশেল থেকে দৌড়ানো পুরো পথটি অতিক্রম করবে না exec, তবে ঠিক সেই পথটি প্রবেশ করেছে। আপনি আপনার উত্তরে এটি সংশোধন করতে পারেন? কি echo "$0"আপনার স্ক্রিপ্টের মধ্যে এবং আপনি এই ক্ষেত্রে দেখা যায় দেখতে হবে।
অ্যান্ডিডগ

2

বাস্তবে, আপনি যদি এটির ফলস্বরূপ গ্রহণ করেন তবে শেবাং লাইনে কার্যকর করা কার্যকর, কেবলমাত্র কার্যকর করা যায়। কিছু পাঠ্য দোভাষীকে এক্সিকিউটেবল হিসাবে ব্যবহার করা বোধগম্য হয় তবে এটি প্রয়োজনীয় নয়। কেবল ব্যাখ্যা এবং প্রদর্শনের জন্য, আমি বরং একটি অকেজো পরীক্ষা করেছি:

#!/bin/cat
useless text
more useless text
still more useless text

ফাইল test.txt নামযুক্ত এবং exectuable বিট সেট chmod u+x test.txt, তাহলে এটি "বলা": ./test.txt। যেমনটি প্রত্যাশা করা হয়েছিল, ফাইলের সামগ্রীগুলি আউটপুট। এই ক্ষেত্রে, বিড়াল শেবাং লাইন উপেক্ষা করে না। এটি কেবল সমস্ত লাইন আউটপুট করে। যে কোনও দরকারী দোভাষী এই শিব্যাং লাইন উপেক্ষা করতে সক্ষম হওয়া উচিত। ব্যাশ, পার্ল এবং পিএইচপি এর জন্য, এটি কেবল একটি মন্তব্য লাইন। হ্যাঁ, এগুলি শেবাং লাইন উপেক্ষা করে।


-1

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

সংক্ষেপে, আপনি কোন শেলটি দিয়ে স্ক্রিপ্টটি চাচ্ছেন তাতে কিছু আসে যায় না - কার্নেল কার্যকরভাবে উভয় উপায়ে এক্সিকিউশনটি প্রেরণ করবে।


4
তার মাঝে একটি চিহ্নিত পার্থক্য bash ./myscript.shএবং ./myscript.sh
একটি সিভিএন

এই "চিহ্নিত পার্থক্য" বলতে কী বোঝ?
jrara

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