সোর্স চালিত না হয়ে শেল স্ক্রিপ্টকে কীভাবে সংজ্ঞায়িত করবেন


40

আমি শেল স্ক্রিপ্টটি সংজ্ঞায়িত করছি যা ব্যবহারকারীর sourceপরিবর্তে ব্যবহারকারীর উচিত ।

ব্যবহারকারীর কাছে ইঙ্গিত দেওয়ার কোনও প্রচলিত বা বুদ্ধিমান উপায় আছে কি উদাহরণস্বরূপ, ফাইল এক্সটেনশনের মাধ্যমে?

আমি নিজেই ফাইলটিতে শেল কোডটি লিখতে পারি, যার ফলে এটি কোনও বার্তা প্রতিধ্বনিত করবে এবং যদি এটি সোর্সিংয়ের পরিবর্তে কার্যকর করা হয় তবে আমি ব্যবহারকারীকে এই সুস্পষ্ট ভুল এড়াতে সহায়তা করতে পারি?


1
সুতরাং, যদি ব্যবহারকারী কোনও এক-লাইন শেল স্ক্রিপ্ট লিখে থাকেন x, যেখানে কেবল কমান্ডটি রয়েছে . your-script-to-be-sourced, এটি ঠিক আছে, তবে যদি তিনি bash your-script-to-be-sourcedএটি সম্পাদন করতে চান তবে এটি নিষিদ্ধ করা উচিত? এই নিষেধাজ্ঞার মূল বিষয় কী?
ব্যবহারকারী 1934428

8
@ user1934428 অবশ্যই এটি কোনও স্ক্রিপ্টের জন্য সাধারণ যা বেশ কয়েকটি envভেরিয়েবল গণনা করে এবং এগুলি ডি-ফ্যাক্টো স্ক্রিপ্টের আউটপুট হিসাবে রেখে দেয় । আপনি যদি তাদের চালানোর অনুমতি দেন তবে কোনও নবজাতক ধাঁধার সাথে কয়েক দিন আটকে থাকবে।
kubanczyk

উত্তর:


45

ধরে নিই যে আপনি বাশ চালাচ্ছেন, স্ক্রিপ্টের শুরুতে নীচের কোডটি লিখুন যা আপনি সস করতে চান তবে সম্পাদন করা হয়নি:

if [ "${BASH_SOURCE[0]}" -ef "$0" ]
then
    echo "Hey, you should source this script, not execute it!"
    exit 1
fi

বাশ-এর ​​আওতায়, ${BASH_SOURCE[0]}বর্তমান ফাইলটির নাম থাকবে যা শেলটি পড়ছে বা তা নির্বাহ করা হচ্ছে তা নির্বিশেষে সেগুলি পড়ছে।

বিপরীতে, $0বর্তমান ফাইলটির নাম কার্যকর করা হচ্ছে।

-efএই দুটি ফাইল একই ফাইল কিনা তা পরীক্ষা করে। যদি সেগুলি হয়, আমরা ব্যবহারকারীকে সতর্ক করে প্রস্থান করব।

আমরাও -efনা BASH_SOURCEPOSIX হয়। যদিও -efksh, যশ, zsh এবং ড্যাশ দ্বারা সমর্থিত, BASH_SOURCEব্যাশ প্রয়োজন। ইনzsh , তবে, ${BASH_SOURCE[0]}দ্বারা প্রতিস্থাপিত হতে পারে ${(%):-%N}


2
সহজভাবে echo "Usage: source \"$myfile\""
kubanczyk

6
@ Kubanczyk sourceপোর্টেবল নয়। এই উত্তরটি বাশ-নির্দিষ্ট বলে বিবেচনা করে, এটি খুব খারাপ নয়, তবে পোর্টেবলটি ব্যবহার করা ভাল অভ্যাস.
gronostaj

33

একটি অ-এক্সিকিউটেবল ফাইলটি উত্সাহিত করা যায় তবে সম্পাদন করা যায় না, সুতরাং প্রতিরক্ষা প্রথম লাইন হিসাবে, নির্বাহী পতাকা নির্ধারণ না করা ভাল ইঙ্গিত হওয়া উচিত ...

সম্পাদনা করুন: কৌতুক আমি কেবল হোঁচট খেয়েছি: শেবাংকে এমন কোনও নির্বাহযোগ্য করে তুলুন যা শেল ইন্টারপ্রিটার নয়, /bin/falseস্ক্রিপ্টটিকে একটি ত্রুটি ফেরায় (আরসি! = 0)

#!/bin/false "This script should be sourced in a shell, not executed directly"

7
তবে একটি অ-এক্সিকিউটেবল ফাইল এখনও উদাহরণস্বরূপ কার্যকর করা যেতে পারে bash somefile.sh...
twalberg

1
যদি আপনি জানেন যে আপনি এটি bash(ভিডি পার্ল, পাইথন, অ্যাজক ...) দিয়ে কার্যকর করতে পারেন , তবে আপনি উত্সটি দেখতে পেয়েছেন এবং মন্তব্যটি করেছেন যা এটি না করার জন্য বলেছে :)
xenoid

1
পার্ল স্ক্রিপ্টগুলির নাম সাধারণত somefile.plপাইথন হিসাবে দেওয়া হয় এবং পাইথন হিসাবে somefile.py, তাই না, সম্ভবত আমি মন্তব্যগুলি পড়িনি (যা সে যাইহোক, সেগুলি কি?) এবং এর bash somefile.shচেয়ে কম টাইপ করতে হবে chmod +x somefile.sh; ./somefile.sh...
twalberg

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

"আপনি যদি জানেন তবে আপনি এটি বাশ দিয়ে সম্পাদন করতে পারেন" উম, না, কখনও কখনও ব্যবহারকারীর কেবল ধারণা থাকে না bash যে এর চেয়ে অন্য শেল রয়েছে এবং এটি bash script.shবিপজ্জনক হতে পারে।
সের্গেই কোলোডিয়াযনি

10

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

সবচেয়ে শক্তিশালী উপায়, যেমন বীরাওয়ান পূর্বওয়ান্টোর পরামর্শ অনুসারে FUNCNAME[1] একটি ফাংশনটির মধ্যে যাচাই করা :

function mycheck() { declare -p FUNCNAME; }
mycheck

তারপর:

$ bash sourcetest.sh
declare -a FUNCNAME='([0]="mycheck" [1]="main")'
$ . sourcetest.sh
declare -a FUNCNAME='([0]="mycheck" [1]="source")'

এটি হ'ল আউটপুট caller, মানগুলি পরীক্ষা করে mainএবং sourceকলারের প্রসঙ্গটি পৃথক করে। ব্যবহার FUNCNAME[]আপনাকে callerআউটপুট ক্যাপচারিং এবং পার্সিং সাশ্রয় করে । সঠিক হওয়ার জন্য আপনার স্থানীয় কলের গভীরতা জানতে বা গণনা করা দরকার। অন্য কোনও ফাংশন বা স্ক্রিপ্টের মধ্যে থেকে কোনও স্ক্রিপ্টের মতো উত্সগুলি সন্ধানের ফলে অ্যারে (স্ট্যাক) আরও গভীর হবে। ( FUNCNAMEএকটি বিশেষ বাশ অ্যারের ভেরিয়েবল, এটি কল স্ট্যাকের সাথে সঙ্গতিপূর্ণ সূচকগুলি হওয়া উচিত, যতক্ষণ না এটি কখনও না is unset)

সুতরাং আপনি স্ক্রিপ্টের শুরুতে যুক্ত করতে পারেন:

function check()
{
    if [[ ${FUNCNAME[-1]} != "source" ]]   # bash 4.2+, use ${FUNCNAME[@]: -1} for older
    then
        printf "Usage: source %s\n" "$0"
        exit 1
    fi
}
check

7

ধরে নেওয়া হ'ল স্ক্রিপ্টটি কার্যকর করার জন্য ক্ষতিকারক না হয়ে এটি কেবল অকেজো

return 0 || printf 'Must be sourced, not executed\n' >&2

থেকে শেষ স্ক্রিপ্ট। returnযদি ফাইলটি উত্সাহিত না করা হয় তবে ফাংশনের বাইরে একটি শূন্য-বহির্গমন প্রস্থান কোড থাকে।


3
দ্রষ্টব্য যে এটি 0 প্রস্থান স্থিতি ফিরে আসে। পরিবর্তে আমি ব্যবহার করি এই একই প্রবাদ ব্যবহার করুন:return 2>/dev/null; echo "$0: This script must be sourced" 1>&2; exit 1
wjandrea

5

যখন আপনি শেল স্ক্রিপ্ট উত্স করেন, শেবাং লাইন উপেক্ষা করা হবে। একটি অবৈধ শেবাং লাগিয়ে আপনি ব্যবহারকারীকে সতর্ক করতে পারেন যে স্ক্রিপ্টটি ভুলভাবে কার্যকর করা হয়েছিল:

#!/bin/bash source-this-script
# ...

ত্রুটি বার্তাটি হ'ল:

/bin/bash: source-this-script: No such file or directory

(নির্বিচারে) যুক্তি নামটি ইতিমধ্যে একটি শক্ত ইঙ্গিত সরবরাহ করে তবে ত্রুটি বার্তাটি এখনও 100% পরিষ্কার নয় clear আমরা কোনও ইউটিলিটি স্ক্রিপ্ট source-this-scriptদিয়ে এটি ঠিক করতে পারি যা আপনার কোথাও রাখা হয়েছে PATH:

#!/bin/sh
echo >&2 "This script must be sourced, not executed${1:+: }${1:-!}"
exit 1

এখন, ত্রুটি বার্তাটি হ'ল:

This script must be sourced, not executed: path/to/script.sh

অন্যান্য পদ্ধতির সাথে তুলনা

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

এটি স্পষ্টভাবে bash path/to/script.shপ্রার্থনা রোধ করে না , যদিও (ধন্যবাদ @ মুরু!)।


1
আরেকটি খারাপ দিক হ'ল এটি এর বিরুদ্ধে সুরক্ষা দেবে না bash some/script.sh, যা শেবাংকে উপেক্ষা করবে।
মুরু

4
আপনি শেবাং #!/bin/echo 'You must source this script!'বা সে জাতীয় কিছু করে বার্তাটি আরও পরিষ্কার করতে পারেন।
ক্রিস

1
@ ক্রিস: ঠিক আছে, তবে তারপরে আমি ফাইল টাইপ সনাক্তকরণ (উদাহরণস্বরূপ ভিমে) এবং কোন শেল ডায়ালিকটি এর ডকুমেন্টেশন হারাব। আপনি যদি এগুলি সম্পর্কে চিন্তা না করেন তবে আপনার পরামর্শটি দ্বিতীয় স্ক্রিপ্ট থেকে মুক্তি পাবে!
ইনগো কারকাত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.