বাশার্ক বর্তমান শেলটি ইন্টারেক্টিভ কিনা তা কেন পরীক্ষা করে?


62

আমার আর্চ ইনস্টল করুন /etc/bash.bashrcএবং /etc/skel/.bashrcএই লাইনগুলি অন্তর্ভুক্ত করুন:

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

দেবিয়ান অন, /etc/bash.bashrcআছে:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

এবং /etc/skel/.bashrc:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

man bashতবে, অনুসারে , অ-ইন্টারেক্টিভ শেলগুলিও এই ফাইলগুলি পড়ে না:

   When  bash  is  started  non-interactively,  to run a shell script, for
   example, it looks for the variable BASH_ENV in the environment, expands
   its  value if it appears there, and uses the expanded value as the name
   of a file to read and execute.  Bash behaves as if the  following  com
   mand were executed:
          if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
   but  the value of the PATH variable is not used to search for the file
   name.

যদি আমি সঠিকভাবে বুঝতে পারি তবে *.bashrcফাইলগুলি কেবল সেগুলিতে BASH_ENVনির্দেশ করা থাকলে সেগুলি পড়বে । এটি এমনটি যা সুযোগ অনুসারে ঘটতে পারে না এবং কেবল তখনই ঘটবে যদি কেউ স্পষ্টভাবে সেই অনুযায়ী চলকটি সেট করে থাকে।

এটি স্ক্রিপ্টগুলির ব্যবহারকারীর .bashrcস্বয়ংক্রিয়ভাবে সেটিংস স্থাপনের সম্ভাবনাটি ভঙ্গ করে বলে মনে হচ্ছে এটি এমন BASH_ENVকিছু যা কার্যকর হতে পারে। প্রদত্ত যে বাশ কখনই এই ফাইলগুলি অ-ইন্টারেক্টিভভাবে চালিত হবে না যখন তা স্পষ্টভাবে না করতে বলা হয়, কেন ডিফল্ট *bashrcফাইলগুলি এটিকে অস্বীকার করে?


5
ব্যবহারিক উত্তরের জন্য, দেখুন এসসিপি ত্রুটি ছাড়াই ব্যর্থ
গিলস

উত্তর:


69

এটি এমন একটি প্রশ্ন যা আমি কয়েক সপ্তাহ আগে এখানে পোস্ট করতে যাচ্ছিলাম। টেরডনের মতো , আমি বুঝতে পেরেছিলাম যে একটি .bashrcকেবল ইন্টারেক্টিভ বাশ শেলের জন্য উত্সাহিত তাই .bashrcএটি কোনও ইন্টারেক্টিভ শেলের মধ্যে চলছে কিনা তা খতিয়ে দেখার দরকার নেই । বিভ্রান্তিকরভাবে, আমি যে সমস্ত বিতরণ ব্যবহার করি (উবুন্টু, আরএইচইল এবং সাইগউইন) বর্তমান শেলটি ইন্টারেক্টিভ কিনা তা নিশ্চিত করার জন্য কিছু প্রকারের চেক (টেস্টিং $-বা $PS1) ছিল। আমি কার্গো কাল্ট প্রোগ্রামিং পছন্দ করি না তাই আমার মধ্যে এই কোডটির উদ্দেশ্য বোঝার বিষয়ে সেট করি .bashrc

রিমোট শেলগুলির জন্য বাশের একটি বিশেষ কেস রয়েছে

সমস্যাটি অনুসন্ধানের পরে, আমি আবিষ্কার করেছি যে দূরবর্তী শেলগুলি অন্যরকম আচরণ করা হয়। অ-ইন্টারেক্টিভ বাশ শেলগুলি সাধারণত ~/.bashrcপ্রারম্ভের সময় কমান্ডগুলি চালায় না , যখন শেলটি রিমোট শেল ডিমন দ্বারা আহ্বান করা হয় তখন একটি বিশেষ কেস তৈরি করা হয় :

কোনও নেটওয়ার্ক সংযোগের সাথে সংযুক্ত তার স্ট্যান্ডার্ড ইনপুট দিয়ে কখন এটি চালিত হচ্ছে তা নির্ধারণের জন্য বাশ চেষ্টা করে, যেমন দূরবর্তী শেল ডিমন দ্বারা চালিত হয় সাধারণত rshd, বা সুরক্ষিত শেল ডিমন দ্বারা চালিত হয় sshd। যদি বাশ নির্ধারণ করে যে এটি এটি এই ফ্যাশনে চালিত হচ্ছে, তবে যদি ফাইলটি বিদ্যমান থাকে এবং পঠনযোগ্য হয় তবে এটি। / .Bashrc থেকে আদেশগুলি পড়ে এবং কার্যকর করে। অনুরোধ করা হলে এটি এটি করবে না sh--norcবিকল্প এই আচরণ দমন করা ব্যবহৃত হতে পারে এবং --rcfileবিকল্প অন্য ফাইল পড়তে হবে জোর করতে ব্যবহার করা যেতে পারে, কিন্তু তন্ন তন্ন rshdনা sshdসাধারণত সেসব বিকল্প সহ শেল ডাকা বা তাদের নির্দিষ্ট করা করার অনুমতি দেয়।

উদাহরণ

রিমোটের শুরুতে নিম্নলিখিতটি প্রবেশ করান .bashrc। (যদি .bashrcদ্বারা sourced হয় .profileবা .bash_profile, অস্থায়ীভাবে এই যখন পরীক্ষামূলক অক্ষম):

echo bashrc
fun()
{
    echo functions work
}

নিম্নলিখিত কমান্ডগুলি স্থানীয়ভাবে চালান:

$ ssh remote_host 'echo $- $0'
bashrc
hBc bash
  • কোন iইন $-ইঙ্গিত দেয় যে শেলটি অ-ইন্টারেক্টিভ
  • কোন নেতৃস্থানীয় -মধ্যে $0ইঙ্গিত করে যে শেল একটি নয় লগ-ইন শেল

রিমোটে সংজ্ঞায়িত শেল ফাংশনগুলিও .bashrcচালানো যেতে পারে:

$ ssh remote_host fun
bashrc
functions work

আমি লক্ষ্য করেছি যে ~/.bashrcহয় শুধুমাত্র যখন একটি কমান্ডের জন্য আর্গুমেন্ট হিসাবে উল্লেখ করা হয় sourced ssh। এটি উপলব্ধি করে: কখন sshএকটি নিয়মিত লগইন শেল শুরু করতে ব্যবহৃত হয়, .profileবা .bash_profileচালানো হয় (এবং .bashrcকেবলমাত্র এই ফাইলগুলির মধ্যে একটি দ্বারা স্পষ্টভাবে এটি করা হলে সোর্স করা হয়)।

.bashrc(নন-ইন্টারেক্টিভ) রিমোট কমান্ড চালানোর সময় আমি সর্বাধিক প্রাপ্তিটি দেখতে পাচ্ছি যে শেল ফাংশনগুলি চালানো যেতে পারে। তবে সাধারণত একটি কমান্ডের বেশিরভাগ কমান্ড .bashrcকেবল ইন্টারেক্টিভ শেলের সাথেই প্রাসঙ্গিক হয়, যেমন শেলটি ইন্টারেক্টিভ না হলে এলিয়াসগুলি প্রসারিত হয় না।

রিমোট ফাইল স্থানান্তর ব্যর্থ হতে পারে

যখন একটি সমস্যা সাধারণত নয় rshবা sshএকটি ইন্টারেক্টিভ লগ-ইন শেল অথবা যখন নন-ইন্টারেক্টিভ শেল কমান্ড চালানোর জন্য ব্যবহার করা হয় শুরু করার জন্য ব্যবহার করা হয়। যাইহোক, এটা একটি সমস্যা হতে পারে যেমন প্রোগ্রামের জন্য rcp, scpএবং sftpব্যবহার দূরবর্তী শাঁস ডেটা ট্রান্সফারের জন্য।

দেখা যাচ্ছে যে scpকমান্ডটি ব্যবহার করার সময় দূরবর্তী ব্যবহারকারীর ডিফল্ট শেল (বাশের মতো) সুস্পষ্টভাবে শুরু হয়েছিল । ম্যান পৃষ্ঠায় এর কোনও উল্লেখ নেই - কেবলমাত্র একটি উল্লেখ যা এর ডেটা স্থানান্তরের জন্য scpব্যবহার করে ssh। এর ফলাফল রয়েছে যে যদি .bashrcস্ট্যান্ডার্ড আউটপুটে মুদ্রিত এমন কোনও কমান্ড থাকে তবে ফাইল স্থানান্তর ব্যর্থ হবে , উদাহরণস্বরূপ, scp ত্রুটি ছাড়াই ব্যর্থ হয়

15 বছর পূর্বে সম্পর্কিত এই রেড হ্যাট বাগ রিপোর্টটি দেখুন, / etc / bashrc এ ইকো কমান্ড উপস্থিত থাকলে scp ব্রেক হয়ে যায় (যা শেষ পর্যন্ত বন্ধ হয়ে গিয়েছিল WONTFIX)।

কেন scpএবং sftpব্যর্থ

এসসিপি (সিকিউর কপি) এবং এসএফটিপি (সিকিউর ফাইল ট্রান্সফার প্রোটোকল) এর ফাইল এবং গুলি স্থানান্তরিত হওয়ার তথ্য আদান-প্রদানের জন্য স্থানীয় এবং দূরবর্তী প্রান্তের নিজস্ব প্রোটোকল রয়েছে। দূরবর্তী প্রান্ত থেকে যে কোনও অপ্রত্যাশিত পাঠ্যটি প্রোটোকলের অংশ হিসাবে ব্যাখ্যা করা হয়েছে (স্থানান্তর) ব্যর্থ হয়েছে। শামুক বইয়ের একটি FAQ অনুসারে

কি প্রায়ই ঘটে, যদিও, হয় সেখানে সার্ভারে পারেন সিস্টেমের মধ্যে বিবৃতি বা ব্যবহারকারী অনুসারে শেল প্রারম্ভকালে ফাইল (আছে .bashrc, .profile, /etc/csh.cshrc, .login, ইত্যাদি) যা লগইনে আউটপুট পাঠ্য বার্তা, অভিপ্রেত মত মানুষের দ্বারা পড়তে হবে ( fortune, echo "Hi there!", ইত্যাদি)।

যখন ttyস্ট্যান্ডার্ড ইনপুটটির সাথে সংযুক্ত থাকে তখন এই জাতীয় কোডটি কেবল ইন্টারেক্টিভ লগইনগুলিতে আউটপুট উত্পাদন করে । যদি এটি এই পরীক্ষাটি না করে তবে এটি এই পাঠ্য বার্তাগুলি যেখানে তাদের অন্তর্ভুক্ত নয় তা সন্নিবেশ করবে: এক্ষেত্রে, এবং scp2/ sftpএবং মধ্যে প্রোটোকল প্রবাহকে দূষিত করে sftp-server

শেল স্টার্টআপ ফাইলগুলি একেবারেই প্রাসঙ্গিক হওয়ার কারণ, এটি হ'ল sshd ব্যবহারকারীর পক্ষে কোনও প্রোগ্রাম শুরু করার সময় ব্যবহারকারীর শেলটি নিয়োগ করে (যেমন, / bin / sh -c "কমান্ড" ব্যবহার করে)। এটি একটি ইউনিক্স traditionতিহ্য, এবং এর সুবিধা রয়েছে:

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

এসসিপি প্রোটোকল বিশদ

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

উদাহরণস্বরূপ, আপনি যদি এটি দূরবর্তী সিস্টেমে আপনার শেল প্রোফাইলে যুক্ত করেন তবে এটি ঘটতে পারে:

প্রতিধ্বনি ""

কেন শুধু ঝুলছে? সোর্স মোডে প্রথম প্রোটোকল বার্তার নিশ্চিতকরণের জন্য যেভাবে অপেক্ষা করা scpহয় তার থেকে এটি আসে । যদি এটি বাইনারি 0 না হয় তবে এটি আশা করে যে এটি কোনও দূরবর্তী সমস্যার একটি বিজ্ঞপ্তি এবং নতুন লাইন না আসা পর্যন্ত আরও অক্ষর একটি ত্রুটি বার্তা গঠনের জন্য অপেক্ষা করে। যেহেতু আপনি প্রথমটির পরে আর একটি নতুন লাইন মুদ্রণ করেন নি, তাই আপনার স্থানীয় কেবল লুপে থাকে, অবরুদ্ধ থাকে । ইতিমধ্যে, শেল প্রোফাইলটি দূরবর্তী পার্শ্বে প্রক্রিয়া করার পরে, সিঙ্ক মোডে শুরু হয়েছিল, যা বাইনারি শূন্যের জন্য অপেক্ষা করে যা ডেটা স্থানান্তর শুরুর নির্দেশ করে।scpread(2)scpread(2)

উপসংহার / টিএলডিআর

আদর্শের বেশিরভাগ বিবৃতি .bashrcকেবল ইন্টারেক্টিভ শেলের জন্যই কার্যকর - যখন rshবা এর সাথে দূরবর্তী কমান্ডগুলি চালিত করে না ssh। সবচেয়ে ধরনের পরিস্থিতি, শেল ভেরিয়েবল, alias লেখা সেটিং এবং ফাংশন কাম্য নয় সংজ্ঞা - এবং মুদ্রণ কোনো টেক্সট আউট মান সক্রিয়ভাবে যেমন প্রোগ্রাম ব্যবহার করে ফাইলগুলি স্থানান্তর যদি ক্ষতিকর scpবা sftp। বর্তমান শেলটি অ-ইন্টারেক্টিভ কিনা তা যাচাই করার পরে প্রস্থান করা সবচেয়ে নিরাপদ আচরণ .bashrc


সুন্দর নিবন্ধ। তবে আমার তা করা উচিত? আমি .বাশার্ক দ্বারা চেক ইন করতে পারি তবে এখনও 0 কোড সহ প্রস্থান করবো এবং রিমোট বাক্সে কোনও কিছুই অনুলিপি করব না
সেস

@ গৃহে একটি নতুন প্রশ্ন জিজ্ঞাসা করা ভাল যেখানে আপনি নিজের পরিস্থিতি আরও বিশদে বর্ণনা করতে পারবেন।
অ্যান্টনি জিওগিগান

16

ম্যান পেজটি উল্লেখ করার জন্য এটি অবহেলা করে যে অন-ইন্টারেক্টিভ দূরবর্তী শেলগুলির জন্য bashউত্সগুলি .bashrcin

ssh hostname command

http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010

 COMMAND        EXECUTE BASHRC
 --------------------------------
 bash -c foo        NO
 bash foo           NO
 foo                NO
 rsh machine ls     YES (for rsh, which calls 'bash -c')
 rsh machine foo    YES (for shell started by rsh) NO (for foo!)
 echo ls | bash     NO
 login              NO
 bash               YES

http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050

          /* If we were run by sshd or we think we were run by rshd, execute
             ~/.bashrc if we are a top-level shell. */
          if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2)
            {
              maybe_execute_file (SYS_BASHRC, 1);
              maybe_execute_file (bashrc_file, 1);

আপনি কি আপনার .bash_profile (বা। প্রোফাইল) থেকে আপনার .bashrc উত্স করেছেন?
গ্লেন জ্যাকম্যান

হ্যাঁ, তবে এটি মূল বিষয় নয়। একটি খালি .bash_profileএকই আচরণ প্রদর্শিত হবে।
মাইকেল

নিশ্চিত না যে এটি আমাকে কী দেখাচ্ছে। আপনি কি বলছেন যে rsh(যা আমি কখনও ব্যবহার করি নি) ~/.bashrc? এবং এটি, এক্সটেনশনের মাধ্যমে লিনাক্স এটিকে অবরুদ্ধ করে bashকেবল যদি কেউ কখনও স্ক্রিপ্ট চালানোর চেষ্টা করে rsh? যেভাবে যাইহোক এটি লগইন শেলটি ssh serverস্পর্শ করা উচিত নয় .bashrc। না, যদি না আপনার সিস্টেম ঐ যে সূত্র ~ / থেকে .bashrc` অন্যতম ~/.profile। এবং ssh server commandএমনকি এটি করা উচিত নয়। অবশ্যই আমার সিস্টেমে না।
terdon

2
না, আমি আপনাকে bashউত্সের সাথে সংযুক্ত করেছি, উত্স নয় rsh। :) মন্তব্যটিও প্রযোজ্য ssh, এটি খুব দীর্ঘকাল আগে লেখা হয়েছিল। আরও উত্স সহ আপডেট উত্তর দেখুন।
মাইকেল

আহ, এটি সহায়ক, আপনাকে ধন্যবাদ। যদিও আমি এটি পরীক্ষা করব? আমি echoএকেবারে শীর্ষে /etc/bash.bashrcএবং ~/.bashrc(ইন্টারেক্টিভ শেল পরীক্ষার আগে) একটি সংযোজন করার চেষ্টা করেছি এবং তারপরে লক্ষ্য মেশিনে এসএসএস করেছি ssh server hostnameএবং চলাকালীন hostnameআমার কোনও প্রতিধ্বনি আমি দেখতে পেলাম না। এটা কি আমার shell_level(যা কিছু) তা নয় <2?
টেরডন

5

কনভেনশন দ্বারা, .bashrcএমন এক জায়গা যেখানে শেলটির জন্য ব্যবহারকারীরা কাস্টমাইজ কনফিগারেশন সঞ্চয় করে।

এই কাস্টমাইজ কনফিগারেশনটি পরিবেশের ভেরিয়েবল, এলিয়াস, অভিনব প্রম্পট হতে পারে। একটি অ-ইন্টারেক্টিভ শেল সহ, জিনিসগুলির সংক্ষেপে অর্থহীন। তদুপরি, একটি অ-ইন্টারেক্টিভ শেলটি অনেক প্রসঙ্গে কল করা যেতে পারে, আপনি নিশ্চিত নন যে সেই পরিবেশের ভেরিয়েবলগুলি মিথ্যা নেতিবাচক কেস বা এমনকি সুরক্ষায় ঝুঁকিপূর্ণ হতে পারে।

নিকটতম উদাহরণ হ'ল একটি উপাধি যেমন:

alias cp='cp -i'

তারপরে এটি আপনার অ-ইন্টারেক্টিভ শেলটিকে চিরতরে স্তব্ধ করে রাখবে।

সুতরাং আমাদের .bashrcযাতে সমস্যা না হয় তা নিশ্চিত করার জন্য চেকটি শীর্ষে সম্পাদন করে ।


যেহেতু শেলটিকে অ-ইন্টারেক্টিভ লগইন শেল হিসাবে ডাকা যেতে পারে , তাই সুস্পষ্টভাবে ব্লক সোর্সিংয়ের *bashrcকোনও অর্থ নেই।

যখন শেল ছিল নন-ইন্টারেক্টিভ লগ-ইন শেল হিসাবে বলা , এটা উৎস /etc/profile, তারপর উৎস প্রথমটি পাওয়া ~/.bash_profile, ~/.bash_loginএবং ~/.profile:

যখন বাশকে একটি ইন্টারেক্টিভ লগইন শেল হিসাবে , বা - লগিন বিকল্পের সাথে একটি অ-ইন্টারেক্টিভ শেল হিসাবে ডাকা হয় , এটি প্রথমে ফাইল / ইত্যাদি / প্রোফাইল থেকে কমান্ডগুলি পড়ে এবং কার্যকর করে, যদি সেই ফাইলটি বিদ্যমান থাকে। এই ফাইলটি পড়ার পরে, এটি সেই ক্রমে ~ / .bash_profile, ~ / .bash_login, এবং ~ /। প্রোফাইলে অনুসন্ধান করে এবং উপস্থিত এবং পঠনযোগ্য যা প্রথমটি থেকে আদেশগুলি পড়ে এবং কার্যকর করে।

এই ফাইলগুলিকে .bashrcনিজেরাই সোর্স করা থেকে বাধা দেয় না, তাই ভিতরে চেক .bashrcকরা নিরাপদ এবং জিনিসগুলি সহজ করে তোলে।


হ্যা, আমি তা জানি. এই কারণেই অ-ইন্টারেক্টিভ শেলগুলি মোটেও *bashrcফাইল উত্স করে না । আমার প্রশ্ন হ'ল এই ফাইলগুলি যদি কোনওভাবেই ইন্টারঅ্যাক্টিভ শেলগুলি না পড়েন তবে বিভিন্ন লিনাক্স বিক্রেতারা কেন এই ফাইলগুলি স্পষ্টরূপে অ-ইন্টারেক্টিভ শেলগুলি এই ফাইলগুলি পড়তে বাধা দেওয়ার সমস্যায় পড়েন।
terdon

1
@ ইটারডন: যেহেতু শেলটিকে অ-ইন্টারেক্টিভ লগইন শেল হিসাবে ডাকা যেতে পারে , তারপরে একটি লগইন শেল উত্স হবে .bash_profile, যা উত্স হতে পারে .bashrc
cuonglm

না, অ-ইন্টারেক্টিভ শেলগুলিতে কেবল পঠনযোগ্য জিনিস $BASH_ENV। উভয়ই *profileএবং *bashrcউপেক্ষা করা হয়। বা, অন্ততপক্ষে, ম্যান পৃষ্ঠাটি এটিই বলে। তবে মাইকেল যেমন দেখিয়েছেন সেই ম্যান পৃষ্ঠাটি মিথ্যা বলে।
টেরডন

@ এটারডন: লিঙ্কটি সহ আমার আপডেট হওয়া উত্তরটি পড়ুন। আপনি কি bash -l -c :একটি ইন্টারঅ্যাক্টিভ লগইন শেলটি চালিত করার চেষ্টা করেছেন ?
cuonglm

কি দারুন. আপনি একদম ঠিক বলছেন. আমি এই অংশটি প্রায় --login100 বার পড়েছি তবে স্পষ্টতই, এটি কখনও নিবন্ধভুক্ত হয়নি। ধন্যবাদ!
টেরডন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.