কোন শেল ইন্টারপ্রেটার কোন শেবাং ছাড়াই স্ক্রিপ্ট চালায়?


17

ধরা যাক আমার অ্যাকাউন্টের জন্য ডিফল্ট শেলটি zsh তবে আমি টার্মিনালটি চালু করে ব্যাশ ফায়ার করেছি এবং একটি স্ক্রিপ্ট prac002.shব্যবহার করেছি, যার শেল ইন্টারপ্রেটারটি স্ক্রিপ্ট, zsh বা বাশ ব্যবহার করতে ব্যবহৃত হবে? নিম্নলিখিত উদাহরণ বিবেচনা করুন:

papagolf@Sierra ~/My Files/My Programs/Learning/Shell % sudo cat /etc/passwd | grep papagolf
[sudo] password for papagolf: 
papagolf:x:1000:1001:Rex,,,:/home/papagolf:/usr/bin/zsh
# papagolf's default shell is zsh

papagolf@Sierra ~/My Files/My Programs/Learning/Shell % bash
# I fired up bash. (See that '%' prompt in zsh changes to '$' prompt, indicating bash.)

papagolf@Sierra:~/My Files/My Programs/Learning/Shell$ ./prac002.sh 
Enter username : Rex
Rex
# Which interpreter did it just use?

** সম্পাদনা: ** স্ক্রিপ্টের বিষয়বস্তু এখানে

papagolf@Sierra ~/My Files/My Programs/Learning/Shell % cat ./prac002.sh 
read -p "Enter username : " uname
echo $uname

স্ক্রিপ্ট শীর্ষে কী বলে?
মাইকেল হোমার

@ মিশেলহোমর: কিছুই না। আমি কেবল স্ক্রিপ্টের বিষয়বস্তু যুক্ত করার জন্য প্রশ্নটি সম্পাদনা করেছি। স্ক্রিপ্টটির কার্যকর করার অনুমতি রয়েছে।
7_আর

আপনি যদি বর্তমান শেলটি ব্যবহার করতে চান . prac002.sh, তবে আপনার স্ক্রিপ্টটি বর্তমান ডিয়ারে রয়েছে তা ধরে রেখে ডট উত্স করুন ।
চিঠিটি

1
চালান . ./prac002.shএবং এটি বর্তমান শেল, যা ডট ( .), স্পেস () দ্বারা আপনার স্ক্রিপ্টের পথ অনুসরণ করে চলবে । একে আপনার স্ক্রিপ্টটি ডট-সোর্সিং বলে। ;-)
দ্য কার্পি

উত্তর:


19

স্ক্রিপ্টটি কোনও #!শেবাং লাইন দিয়ে শুরু হয় না যা নির্দেশ করে কোন দোভাষী ব্যবহার করবেন, POSIX বলেছেন :

execl()POSIX.1-2-2008 এর সিস্টেম ইন্টারফেস ভলিউমে সংজ্ঞায়িত [ENOEXEC] ত্রুটির সমতুল্য ত্রুটির কারণে যদি ফাংশনটি ব্যর্থ হয় তবে শেলটি প্রথম হিসাবে অনুসন্ধানের ফলে পাথের সাথে শেলটি যুক্ত হওয়ার সমান একটি কমান্ড কার্যকর করবে shall অপরেনড , নতুন শেলের কাছে বাকী কোনও আর্গুমেন্ট সহ, নতুন শেলের মধ্যে "$ 0" এর মান কমান্ড নাম হিসাবে সেট করা যেতে পারে। যদি এক্সিকিউটেবল ফাইলটি কোনও টেক্সট ফাইল না হয়, শেলটি এই আদেশটি কার্যকর করতে পারে। এই ক্ষেত্রে, এটি একটি ত্রুটি বার্তা লিখবে এবং 126 এর প্রস্থান স্থিতি ফিরিয়ে আনবে।

এই ফ্রেসিংটি কিছুটা অস্পষ্ট এবং বিভিন্ন শেলের বিভিন্ন ব্যাখ্যা রয়েছে।

এই ক্ষেত্রে, বাশ নিজেই স্ক্রিপ্টটি চালাবে । অন্যদিকে, যদি আপনি এটি zsh থেকে দৌড়ে পরিবর্তে, zsh ব্যবহার করেনsh (যাই হোক না কেন যে আপনার সিস্টেমে হয়) পরিবর্তে।

স্ক্রিপ্টে এই লাইনগুলি যুক্ত করে আপনি এই মামলার জন্য সেই আচরণটি যাচাই করতে পারেন:

echo $BASH_VERSION
echo $ZSH_VERSION

আপনি নোট করবেন, বাশ থেকে, প্রথম লাইনটি আপনার সংস্করণটি আউটপুট করে, যখন দ্বিতীয়টি কখনই কিছুই বলে না, আপনি কোনও শেল ব্যবহার করেন না কেন।

  • যদি আপনার /bin/shহয়, বলুন, dashতখন zsh বা ড্যাশ থেকে স্ক্রিপ্টটি কার্যকর করা হয় না তখনই কোনও লাইনই কিছুই আউটপুট দেয় না।
  • যদি আপনার /bin/shবাশের লিঙ্ক হয় তবে আপনি সমস্ত ক্ষেত্রে প্রথম লাইন আউটপুট দেখতে পাবেন।
  • যদি /bin/shএকটি হয় ভিন্ন সংস্করণ চেয়ে আপনি সরাসরি ব্যবহার করা হয়েছে ব্যাশ, আপনি বিভিন্ন আউটপুট যখন আপনি সরাসরি এবং zsh থেকে ব্যাশ থেকে স্ক্রিপ্ট চালানোর দেখতে পাবেন।

ps -p $$Rools এর উত্তর থেকে কমান্ড এছাড়াও কমান্ড শেল স্ক্রিপ্ট সঞ্চালনের জন্য ব্যবহৃত সম্পর্কে গুরুত্বপূর্ণ তথ্য প্রদর্শন করবে।


আমি আপভোট করেছি, তবে, কোনও শেবাং নির্দিষ্ট না করা থাকলে এটি ডিফল্ট শেল ব্যবহার করে, আপনি যেটি ডিফল্ট শেল নির্দিষ্ট করেছেন। এজন্য আপনার সর্বদা, ইমো, একটি শেবাং নির্দিষ্ট করা উচিত।
thecarpy

4
এটি না, যা সত্যই উত্তর পুরো পয়েন্ট ছিল। আপনার দ্বিতীয় বাক্যটি অবশ্যই সত্য।
মাইকেল হোমার

আপনি ঠিক বলেছেন, বাশ নিজেই এটি ব্যবহার করে চালায়, আমার বেশিরভাগ বাক্সের ডিফল্ট শেলটি ঘটে .... ব্যাশ, সেখান থেকে আমার বিভ্রান্তি। আমি সোলারিস 8 এ ডিএসএল ডিফল্ট শেল হিসাবে ksh দিয়ে পরীক্ষা করেছি, যথেষ্ট নিশ্চিত, ব্যাশ এটি ব্যাশ হিসাবে চালায় ... আজ নতুন কিছু শিখেছে, ধন্যবাদ (
উর্ধ্বতন

ধন্যবাদ। execl()যখন শেল স্ক্রিপ্টে একটি শেবাং না থাকে এবং হিসাবে সম্পাদিত হয় তখন কি কল ব্যর্থতা ঘটে scriptname? শেল স্ক্রিপ্ট হিসাবে কার্যকর হলে এটি ঘটে না bash scriptname? যখন শেল স্ক্রিপ্টে একটি শেবাং থাকে এবং তেমন কার্যকর হয় তখন scriptnameকী ঘটে না ?
সমস্ত 15


7

যেহেতু ফাইলটি কোনও প্রকারের এক্সিকিউটেবল সিস্টেমের দ্বারা স্বীকৃত নয়, এবং ধরে নিই যে আপনি এই ফাইলটি সম্পাদন করার অনুমতি পেয়েছেন, তাই execve()সিস্টেম কলটি সাধারণত একটি ENOEXEC( কার্যকরযোগ্য নয় ) ত্রুটির সাথে ব্যর্থ হবে ।

এরপরে যা ঘটে তা হ'ল কমান্ডটি কার্যকর করতে ব্যবহৃত অ্যাপ্লিকেশন এবং / অথবা লাইব্রেরি ফাংশন to

এটি উদাহরণস্বরূপ শেল, execlp()/ execvp()libc ফাংশন হতে পারে।

কমান্ড চালানোর সময় বেশিরভাগ অন্যান্য অ্যাপ্লিকেশন সেগুলির মধ্যে দুটিই ব্যবহার করবে। তারা system("command line")libc ফাংশনের মাধ্যমে উদাহরণস্বরূপ একটি শাঁস আহ্বান করবে যা সাধারণত shকমান্ড লাইনটি পার্স করার জন্য আহ্বান জানায় (যার পথটি সংকলন সময়ে নির্ধারণ করা যায় ( সোলারিসের মতো /bin/shবনাম /usr/xpg4/bin/sh)), বা $SHELLনিজের দ্বারা সঞ্চিত শেলটি অনুরোধ করবে viএটির !কমান্ড সহ, বা আরও xterm -e 'command line'অনেকগুলি কমান্ড ( su user -cব্যবহারকারীর লগইন শেলটির পরিবর্তে অনুরোধ করবে $SHELL)।

সাধারণত, একটি শেবাং-কম পাঠ্য ফাইল যা শুরু হয় না #এটি একটি shস্ক্রিপ্ট হিসাবে বিবেচনা করা হয় । যা shএটি হ'ল তবে তারতম্য হবে।

execlp()/ execvp(), execve()ফিরে আসার পরে এটি ENOEXECসাধারণত অনুরোধ shকরবে। যেসব সিস্টেমে একের অধিক shসংস্থাগুলি রয়েছে কারণ তারা একাধিক মান মেনে চলতে পারে, যা shসাধারণত এটি সংকলনের সময় নির্ধারিত হবে (অ্যাপ্লিকেশনটি কোডের একটি ভিন্ন ব্লবকে ব্যবহার করে execvp()/ execlp()যা একটি পৃথক পথ নির্দেশ করে sh)) উদাহরণস্বরূপ, সোলারিসে, এটি হয় /usr/xpg4/bin/sh(একটি স্ট্যান্ডার্ড, পসিক্স sh) বা /bin/sh(সোলারিস 10 এবং তার চেয়ে পুরনো বোর্ন শেল (একটি প্রাচীন শেল), সোলারিস 11 এ ksh93) হবে।

এটি শাঁসের ক্ষেত্রে যখন আসে তখন প্রচুর তারতম্য হয়। bash, এটিএন্ডটি ksh, বোর্ন শেল সাধারণত স্ক্রিপ্টটি ব্যাখ্যা করবে (একটি শিশু প্রক্রিয়ায় execব্যবহৃত না হওয়া পর্যন্ত ) একটি সিমুলেট করার পরে execve(), যা সমস্ত অপরিবর্তিত ভেরিয়েবলগুলি আনসেট করা হয়, সমস্ত অন-এক্সিকিউট এফডি বন্ধ করে দেয়, সমস্ত কাস্টম ট্র্যাপগুলি সরিয়ে দেয়, উপকরণ, ফাংশন ... ( bashস্ক্রিপ্টটি shমোডে ব্যাখ্যা করবে )। yashনিজেই চালানো হবে (সঙ্গে shযেমন argv[0]তাই shএটা ব্যাখ্যা করা মোড)।

zsh, pdksh, ashভিত্তিক শেল সাধারণত ডাকা হবে sh(পথ সংকলন সময়ে যার নির্ধারিত)।

জন্য cshএবং tcsh(এবং shকিছু গোড়ার দিকে BSD গুলোর এর), যদি ফাইলের প্রথম চরিত্র #, তারপর তারা নিজেদের এটা ব্যাখ্যা করা, এবং চালানো হবে shঅন্যথায়। এটি পূর্ব-শেবাং সময়ে ফিরে যায় যেখানে মন্তব্য হিসাবে cshস্বীকৃতি পেল #কিন্তু বোর্ন শেল নয়, সুতরাং #এটি একটি সিএস স্ক্রিপ্ট ছিল এমন ইঙ্গিত ছিল।

fish(কমপক্ষে সংস্করণ ২.৪.০), execve()ব্যর্থ হলে কেবল একটি ত্রুটি প্রদান করে (এটি এটি কোনও স্ক্রিপ্ট হিসাবে বিবেচনা করার চেষ্টা করে না)।

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

এছাড়াও মনে রাখবেন যে execve()ENOEXEC এ ব্যর্থ হয়ে থাকলেও ফাইলটিতে একটি শেবাং লাইন থাকে তবে কিছু শেল সেগুলি শেবাং লাইনকে নিজেরাই ব্যাখ্যা করার চেষ্টা করে।

সুতরাং কয়েকটি উদাহরণ:

  • যখন $SHELLহয় /bin/bash, xterm -e 'myscript with args'হবে myscriptব্যাখ্যা bashমধ্যে shমোড। সঙ্গে যদিও xterm -e myscript with args, xtermব্যবহার করবে execvp(), যাতে স্ক্রিপ্ট দ্বারা ব্যাখ্যা করা হবে sh
  • su -c myscriptসোলারিস 10 এ যেখানে rootলগইন শেলটি /bin/shএবং /bin/shবোর্ন শেলটি বোর্ন শেল myscriptদ্বারা ব্যাখ্যা করা হবে ।
  • /usr/xpg4/bin/awk 'BEGIN{system("myscript")'সোলারিস 10 এ এটির দ্বারা ব্যাখ্যা করা হবে /usr/xpg4/bin/sh(একই জন্য /usr/xpg4/bin/env myscript)।
  • find . -prune -exec myscript {} \;সোলারিস 10 তে (ব্যবহার করে execvp()) এটির /bin/shসাথে /usr/xpg4/bin/findএমনকি পসিক্স পরিবেশে (একটি কনফরমেশন বাগ) ব্যাখ্যাও করবে।
  • csh -c myscriptঅন্যথায় , cshএটি দিয়ে শুরু হলে এটি দ্বারা ব্যাখ্যা করা হবে ।#sh

সব মিলিয়ে আপনি নিশ্চিত হতে পারবেন না যে কীভাবে এবং কীভাবে এটি চাওয়া হবে তা যদি আপনি না জানেন তবে সেই স্ক্রিপ্টটির ব্যাখ্যার জন্য কোন শেল ব্যবহার করা হবে।

যাইহোক , read -pকেবলমাত্র bashসিনট্যাক্স, সুতরাং আপনি নিশ্চিত করতে চাইবেন যে স্ক্রিপ্টটি ব্যাখ্যা করেছে bash(এবং সেই বিভ্রান্তিমূলক .shএক্সটেনশন এড়াতে )। হয় আপনি কার্যকর bashএবং ব্যবহারের পথ জানেন :

#! /path/to/bash -
read -p ...

অথবা আপনি $PATHব্যবহার করে bashএক্সিকিউটেবল (ধরে নিচ্ছেন bashইনস্টল করা) এর একটি দৃশ্যের উপর নির্ভর করতে এবং ব্যবহার করতে পারেন:

#! /usr/bin/env bash
read -p ...

( envপ্রায় সর্বব্যাপী পাওয়া যায় /usr/bin)। বিকল্পভাবে, আপনি এটিকে পসিক্স + বোর্ন সামঞ্জস্য করতে পারেন যা আপনি ব্যবহার করতে পারেন /bin/sh। সমস্ত সিস্টেমে ক /bin/sh। তাদের বেশিরভাগের ক্ষেত্রে এটি (বেশিরভাগ অংশের) পসিক্স-সামঞ্জস্যপূর্ণ হবে তবে আপনি তারপরে এখনও এবং তারপরে একটি বোর্ন শেলটি খুঁজে পেতে পারেন।

#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"

1

যখন আপনার কোনও #!( শেবাং ) লাইন না থাকে, তখন sh ব্যবহার করা হয়। এটি যাচাই করতে আপনি নিম্নলিখিত স্ক্রিপ্টটি চালাতে পারেন।

ps -p $$
echo -n "The real shell is: "
realpath /proc/$$/exe

আমার কম্পিউটারে পেয়েছি

  PID TTY          TIME CMD
13718 pts/16   00:00:00 sh
The real program is: /usr/bin/bash

এমনকি যদি আমার ডিফল্ট শেলটি zsh হয় । এটি আমার মেশিনে ব্যাশ ব্যবহার করে, sh কমান্ড ব্যাশ দ্বারা প্রয়োগ করা হয় ।


1
কেন আপনি এটাকে নিম্নচোট করলেন? দয়া করে ব্যাখ্যা করুন বা এটি অকেজো ...
রোল

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