নোড ফাইলের শুরুতে "/ usr / bin / env নোড" ঠিক কী করে?


109

আমি #!/usr/bin/env nodeকয়েকটি উদাহরণের শুরুতে এই লাইনটি দেখেছি nodejsএবং আমি কোনও বিষয় খুঁজে না পেয়ে গুগল করেছিলাম যা এই লাইনের কারণটির উত্তর দিতে পারে।

শব্দের প্রকৃতি অনুসন্ধানটিকে এত সহজ করে না।

আমি কিছু পড়তাম javascriptএবংnodejs সম্প্রতি বই সেগুলির কোনওটিতে এটি দেখে মনে ।

আপনি যদি একটি উদাহরণ চান, আপনি RabbitMQঅফিসিয়াল টিউটোরিয়ালটি দেখতে পেতেন , তাদের প্রায় সব উদাহরণে এটি রয়েছে, তাদের মধ্যে একটি এখানে রয়েছে:

#!/usr/bin/env node

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://localhost', function(err, conn) {
  conn.createChannel(function(err, ch) {
    var ex = 'logs';
    var msg = process.argv.slice(2).join(' ') || 'Hello World!';

    ch.assertExchange(ex, 'fanout', {durable: false});
    ch.publish(ex, '', new Buffer(msg));
    console.log(" [x] Sent %s", msg);
  });

  setTimeout(function() { conn.close(); process.exit(0) }, 500);
});

কেউ আমাকে ব্যাখ্যা করতে পারে এই লাইনের অর্থ কী?

আমি এই লাইনটি রাখি বা সরিয়ে দিলে পার্থক্য কী? কোন ক্ষেত্রে আমার এটির দরকার?


3
এটি মূলত কলিং শেলটির পরিবেশ নেয় এবং যে অ্যাপ্লিকেশন নির্দিষ্ট করা থাকে সেই পরিবেশটিকে স্টফ করে। এই ক্ষেত্রে,node
মার্ক বি

আসলে না, আমি উইন্ডোজ থেকে আসছি না, তবে আপনার উত্তরটি আপডেট করার জন্য আপনাকে ধন্যবাদ। আমি কেবল অপেক্ষায় রয়েছি যে অন্য কেউ মতবিরোধী মতামত নিয়ে আসে কিনা। একটি মাত্র জিনিস আছে যা আমি মনে করি আপনি নিজের উত্তরে উল্লেখ করেন নি, কয়েক ঘন্টা আগে আমি এটি খুঁজে পেয়েছি। তারা এখানে যে জিনিসগুলি উল্লেখ করেছে তা এক ধরণের গুরুত্বপূর্ণ বলে মনে হচ্ছে তবে এটি এখনও আমার পক্ষে যথেষ্ট পরিষ্কার নয়। stackoverflow.com/questions/14517535/… (আপনি চাইলে আপডেট করতে পারেন, আমি সত্যিই এটিকে প্রশংসা করব, তবে এটি কোনও বাধ্যবাধকতার মতো মনে হয় না, আপনার উত্তর এখনই যথেষ্ট ভাল)।
জিপসার

@ গেপসার: বুঝেছি এর সংক্ষিপ্তসারটি হ'ল: আপনি যদি npmকোনও নোড.জেএস উত্স স্ক্রিপ্টটি (সম্ভাব্য বিশ্বজুড়ে উপলভ্য) সিএলআই হিসাবে ইনস্টল করতে চান তবে আপনাকে অবশ্যই শেবাং লাইন ব্যবহার করতে হবে - এবং npmএমনকি উইন্ডোজটিতে সেই কাজটি করা হবে; আমার আবার আপডেট উত্তর দেখুন।
mklement0

"শব্দের প্রকৃতি অনুসন্ধানটিকে এত সহজ করে তোলে না" - আপনি এই নির্দিষ্ট অনুসন্ধানের ব্যবহারের জন্য duckduckgo.com চেষ্টা করতে চাইতে পারেন
রিকার্ডো ২

উত্তর:


146

#!/usr/bin/env nodeহয় একটি একটি দৃষ্টান্ত কুঁড়েঘর লাইন : উপর একটি এক্সিকিউটেবল প্লেইন-টেক্সট ফাইল খুব প্রথম লাইন ইউনিক্সের মত প্ল্যাটফর্মের সিস্টেম কি ব্যাখ্যাকারী সঞ্চালনের জন্য যে ফাইল পাস বলে কমান্ড লাইন জাদু নিম্নলিখিত মাধ্যমে #!উপসর্গ (নামক কুঁড়েঘর ) ।

দ্রষ্টব্য: উইন্ডোজ শেবাং লাইনগুলিকে সমর্থন করে না , সুতরাং তারা কার্যকরভাবে সেখানে অগ্রাহ্য হয়; উইন্ডোজে এটি কেবলমাত্র একটি প্রদত্ত ফাইলের ফাইল নাম এক্সটেনশন যা নির্বাহযোগ্য এটির অর্থ কী তা ব্যাখ্যা করবে es যাইহোক, আপনি এখনও প্রসঙ্গে তাদের প্রয়োজনnpm[1]

শেবাং লাইনের নিম্নলিখিত, সাধারণ আলোচনাটি ইউনিক্সের মতো প্ল্যাটফর্মগুলির মধ্যে সীমাবদ্ধ:

নিম্নলিখিত আলোচনায় আমি ধরে নেব যে নোড.জেএস দ্বারা কার্যকর করার জন্য উত্স কোড যুক্ত ফাইলটির নাম সহজভাবে দেওয়া হয়েছে file

  • আপনার এই লাইনটির প্রয়োজন , আপনি যদি কোনও নোড.জেএস উত্স ফাইলটি সরাসরি ডানতে এক্সিকিউটেবল হিসাবে চান - এটি ধরে নেয় যে ফাইলটি একটি কমান্ডের সাথে এক্সিকিউটেবল হিসাবে চিহ্নিত হয়েছে chmod +x ./file, যা আপনাকে ফাইলটি আহ্বান করার অনুমতি দেয় উদাহরণস্বরূপ, ./fileবা, যদি এটি $PATHভেরিয়েবলের তালিকাভুক্ত ডিরেক্টরিগুলির মধ্যে একটিতে অবস্থিত থাকে তবে কেবল file

    • বিশেষত, কোনও এনপিএম প্যাকেজের অংশ হিসাবে নোড.জেএস উত্স ফাইলের উপর ভিত্তি করে সিএলআই তৈরি করতে আপনার একটি শেবাং লাইন প্রয়োজন, প্যাকেজের ফাইলের কী এর মানের উপর ভিত্তি করে সি এল এল (গুলি) ইনস্টল করতে হবে ; বিশ্বব্যাপী ইনস্টল করা প্যাকেজগুলির সাথে কীভাবে এটি কাজ করে তার জন্য এই উত্তরটি দেখুন । পাদটীকা [1] উইন্ডোতে কীভাবে এটি পরিচালনা করা হয় তা দেখায়।npm"bin"package.json
  • আপনি প্রয়োজন হবে না স্পষ্টভাবে এর মাধ্যমে একটি ফাইল ডাকা এই লাইন nodeব্যাখ্যাকারী, যেমন,node ./file


Backgroundচ্ছিক পটভূমি তথ্য :

#!/usr/bin/env <executableName>স্পষ্টতই একটি দোভাষীকে নির্দিষ্ট করার একটি উপায় : সংক্ষেপে এটি বলে: <executableName>আপনি যেখানে (প্রথমে) এটি $PATHভেরিয়েবলের তালিকাভুক্ত ডিরেক্টরিগুলির মধ্যে খুঁজে পান (এবং স্পষ্টতই এটি হস্তান্তরিত ফাইলের পথটি প্রেরণ করুন) কার্যকর করুন।

এটি হ'ল কোনও প্রদত্ত দোভাষী অন্য প্ল্যাটফর্ম জুড়ে বিভিন্ন স্থানে ইনস্টল করা হতে পারে যা nodeনোড.জেএস বাইনারি হিসাবে অবশ্যই রয়েছে।

বিপরীতে, envইউটিলিটির অবস্থান নিজেই প্ল্যাটফর্মগুলির জুড়ে একই জায়গায় নির্ভর করা যেতে পারে , /usr/bin/env- এবং এক্সিকিউটেবলের পুরো পথ নির্দিষ্ট করে প্রয়োজনীয় একটি শিবং লাইনে ।

নোট করুন যে POSIX ইউটিলিটি ফাইল নাম দ্বারা সনাক্ত করতে এবং এর মধ্যে একটি এক্সিকিউটেবল কার্যকর করতে এখানে পুনঃপ্রবর্তিতenv হচ্ছে । আসল উদ্দেশ্য হ'ল পরিবেশটি একটি কমান্ডের জন্য পরিচালনা করা - দেখুন পোসিক্স স্পেস এবং কীথ থম্পসনের সহায়ক উত্তর$PATH
envenv


এটাও লক্ষণীয় যে নোড.জেএস শেবাং লাইনের জন্য একটি সিনট্যাক্স ব্যতিক্রম করে দিচ্ছে যে তারা জাভাস্ক্রিপ্ট কোডটি বৈধ নয় (জাভাস্ক্রিপ্টে #কোনও মন্তব্য চরিত্র নয়, পসিক্সের মতো শেল এবং অন্যান্য অনুবাদকদের তুলনায়)।


[1] ক্রস-প্ল্যাটফর্মের ধারাবাহিকতার স্বার্থে, একটি প্যাকেজের ফাইলে নির্দিষ্ট করা এক্সিকিউটেবল ইনস্টল করার সময় উইন্ডোজে র্যাপার ফাইলগুলি (ব্যাচ ফাইলগুলি) npmতৈরি করে ( *.cmd সম্পত্তির package.jsonমাধ্যমে "bin")। মূলত, এই মোড়ক ব্যাচের ফাইলগুলি ইউনিক্স শেবাং কার্যকারিতা নকল করে: তারা লক্ষ্য করে ফাইলটি শিবাং লাইনে নির্দিষ্ট করা এক্সিকিউটেবলের সাথে স্পষ্টভাবে অনুরোধ করে - এইভাবে, আপনার স্ক্রিপ্টগুলিতে অবশ্যই শেবাং লাইন অন্তর্ভুক্ত করা উচিত এমনকি যদি আপনি কেবল উইন্ডোজ এ চালানোর ইচ্ছা করেন - এই উত্তরটি দেখুন আমার বিবরণ জন্য।
যেহেতু *.cmdফাইলগুলি ছাড়াও প্রার্থনা করা যেতে পারে.cmdএক্সটেনশন, এটি একটি npmবিরামবিহীন ক্রস-প্ল্যাটফর্মের অভিজ্ঞতা তৈরি করে: উইন্ডোজ এবং ইউনিক্স উভয় ক্ষেত্রেই আপনি কার্যকরভাবে একটি ইনস্টল করা সিএলআই এর মূল, এক্সটেনশন-কম নাম দিয়ে আবেদন করতে পারেন ।


আপনি কি আমার মতো ডামিগুলির জন্য ব্যাখ্যা বা সংক্ষিপ্তসার সরবরাহ করতে পারেন?
অ্যান্ড্রু ল্যাম

4
@ অ্যান্ড্রুল্যাম: উইন্ডোজে, ফাইলের নাম এক্সটেনশনগুলি যেমন .cmdএবং ফাইল .pyনির্ধারণের জন্য কোন প্রোগ্রামটি ব্যবহৃত হবে তা নির্ধারণ করে। ইউনিক্সে, শেবাং লাইন সেই ফাংশনটি সম্পাদন করে। npmসমস্ত সমর্থিত প্ল্যাটফর্মগুলিতে কাজ করার জন্য , আপনার উইন্ডোজ এমনকি শ্যাবাং লাইন প্রয়োজন।
mklement0

28

দোভাষী দ্বারা সম্পাদিত হওয়া যে স্ক্রিপ্টগুলি সাধারণত ওএসকে কার্যকর করতে হয় তা জানানোর জন্য শীর্ষে একটি শেবাং লাইন থাকে।

আপনার যদি কোনও স্ক্রিপ্ট থাকে fooযার নাম প্রথম রেখা#!/bin/sh সিস্টেমটি সেই প্রথম লাইনটি পড়বে এবং এর সমতুল্য সম্পাদন করবে /bin/sh foo। এ কারণে, বেশিরভাগ দোভাষীকে একটি স্ক্রিপ্ট ফাইলের নাম কমান্ড-লাইন আর্গুমেন্ট হিসাবে গ্রহণ করার জন্য সেট আপ করা হয়।

নিম্নলিখিত দোভাষী এর নাম #! পুরো পথ হতে হবে; $PATHদোভাষী খুঁজে পেতে ওএস আপনাকে অনুসন্ধান করবে না ।

যদি আপনার দ্বারা সম্পাদিত কোনও স্ক্রিপ্ট থাকে nodeতবে প্রথম লাইনটি লেখার সুস্পষ্ট উপায় হ'ল:

#!/usr/bin/node

nodeকমান্ডটি ইনস্টল না করা থাকলে এটি কার্যকর হয় না /usr/bin

envকমান্ডটি ব্যবহার করা (যা সত্যই এই উদ্দেশ্যে করা হয়নি):

#!/usr/bin/env node

যদি আপনার স্ক্রিপ্ট বলা হয় foo, ওএস এর সমতুল্য কাজ করবে

/usr/bin/env node foo

envকমান্ড আরেকটি কমান্ড যার নাম তার কমান্ড লাইন দেওয়া হয় executes, যে কমান্ড কোনো নিম্নলিখিত আর্গুমেন্ট ক্ষণস্থায়ী। এটি এখানে ব্যবহার করার কারণ হ'ল কমান্ডটি envঅনুসন্ধান করবে $PATH। তাই আপনি যদি nodeইনস্টল করা হয় /usr/local/bin/node, এবং আপনি /usr/local/binআপনার $PATH,env কমান্ডটি অনুরোধ করা হবে /usr/local/bin/node foo

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

এই পদ্ধতির কিছু ত্রুটি রয়েছে। বেশিরভাগ আধুনিক ইউনিক্স-মতো সিস্টেম রয়েছে /usr/bin/envতবে আমি পুরানো সিস্টেমগুলিতে কাজ করেছি যেখানে envকমান্ডটি একটি ভিন্ন ডিরেক্টরিতে ইনস্টল করা হয়েছিল। এই তত্ত্বটি ব্যবহার করে আপনি অতিরিক্ত যুক্তিগুলি সীমাবদ্ধ করতে পারেন pass ব্যবহারকারীর যদিnode কমান্ডটি অন্তর্ভুক্ত ডিরেক্টরিটি না রাখে$PATH বা তার কাছে কিছু আলাদা কমান্ড কল করা থাকে node, তবে এটি ভুল কমান্ডটি ডেকে আনতে পারে বা এগুলি কাজ করে না।

অন্যান্য পদ্ধতিগুলি হ'ল:

  • কমান্ডের #!সম্পূর্ণ পথ নির্দিষ্ট করে এমন একটি লাইন ব্যবহার করুন node, বিভিন্ন সিস্টেমের জন্য প্রয়োজনীয় স্ক্রিপ্টটি আপডেট করে; অথবা
  • nodeআর্গুমেন্ট হিসাবে আপনার স্ক্রিপ্টের সাথে আদেশটি আহ্বান করুন ।

কৌশল সম্পর্কে আরও আলোচনার জন্য এই প্রশ্নটি (এবং আমার উত্তর ) দেখুন #!/usr/bin/env

উল্লেখ্য, আমার সিস্টেম (লিনাক্সের মিন্ট 17.2), এটি যেমন ইনস্টল /usr/bin/nodejs। আমার নোট অনুযায়ী থেকে পরিবর্তিত /usr/bin/nodeকরা /usr/bin/nodejsউবুন্টু 12.04 এবং 12.10 মধ্যে। #!/usr/bin/envকৌতুক দিয়ে সাহায্য করবে না (যদি না আপনি একটি সিমবলিক লিঙ্ক বা কিছু অনুরূপ সেট আপ)।

আপডেট: এমট্রেসিয়রের একটি মন্তব্য বলেছেন (পুনরায় ফর্ম্যাট করা):

নোডেজ বনাম নোড সমস্যার জন্য একটি কার্যনির্বাহীকরণটি নিম্নলিখিত ছয়টি লাইন দিয়ে ফাইলটি শুরু করা:

#!/bin/sh -
':' /*-
test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
test2=$(node --version 2>&1) && exec node "$0" "$@"
exec printf '%s\n' "$test1" "$test2" 1>&2
*/

এটি প্রথমে চেষ্টা করবে nodejsএবং তারপরে চেষ্টা করবে nodeএবং দু'টি খুঁজে পাওয়া না গেলে কেবল ত্রুটি বার্তাগুলি মুদ্রণ করবে। একটি ব্যাখ্যা এই মন্তব্যগুলির আওতার বাইরে, আমি উত্তরটি সমস্যাটি যেহেতু কারওর সাথে এই সমস্যাটির মোকাবেলা করতে সহায়তা করে তবেই আমি এটিকে এখানে রেখে যাচ্ছি।

আমি ইদানীং নোডজেএস ব্যবহার করিনি। আমার আশা হ'ল আমি প্রথম এই উত্তরটি পোস্ট করার পর থেকেই nodejsভার্সেস nodeইস্যুটি সমাধান হয়ে গেছে। উবুন্টু 18.04-এ, nodejsপ্যাকেজটি এতে /usr/bin/nodejsএকটি সিমিলিংক হিসাবে ইনস্টল করে /usr/bin/node। পূর্ববর্তী কয়েকটি ওএসে (উবুন্টু বা লিনাক্স মিন্ট, আমি নিশ্চিত না কোনটি), সেখানে একটি nodejs-legacyপ্যাকেজ ছিল যা nodeসিমলিংক হিসাবে সরবরাহ করেছিল nodejs। আমার কাছে সমস্ত বিবরণ সঠিক আছে এমন কোনও গ্যারান্টি নেই।


একটি খুব পুঙ্খানুপুঙ্খ উত্তর কেন জিনিস সরবরাহ করে।
সুরজ জৈন

1
জন্য একটি কার্যসংক্রান্ত nodejsবনাম node1): সমস্যা নিম্নলিখিত ছয় লাইনের ফাইল শুরু করার #!/bin/sh -, 2) ':' /*-3) test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"4) test2=$(node --version 2>&1) && exec node "$0" "$@", 5) exec printf '%s\n' "$test1" "$test2" 1>&26) */। এটি প্রথমে চেষ্টা করবে nodejsএবং তারপরে চেষ্টা করবে nodeএবং দু'টি খুঁজে পাওয়া না গেলে কেবল ত্রুটি বার্তাগুলি মুদ্রণ করবে। একটি ব্যাখ্যা এই মন্তব্যগুলির আওতার বাইরে, আমি উত্তরটি সমস্যাটি যেহেতু কারওর সাথে এই সমস্যাটির মোকাবেলা করতে সহায়তা করে তবেই আমি এটিকে এখানে রেখে যাচ্ছি।
mtraceur

@ মিটারেসর: আমি আপনার মন্তব্যে আমার উত্তরে অন্তর্ভুক্ত করেছি। কেন -উপর #!লাইন?
কিথ থম্পসন

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

প্রযুক্তিগতভাবে প্রথম আর্গুমেন্ট হিসাবে একক ড্যাশটির অর্থ "বিকল্পগুলির সমাপ্তি" নয় - এটি প্রাথমিকভাবে "বন্ধ -xএবং -v" হিসাবে বোঝায় , তবে যেহেতু প্রথম দিকে বোর্ন-পছন্দগুলি কেবল সম্ভাব্য বিকল্প হিসাবে প্রথম যুক্তিকে পার্স করেছিল, এবং যেহেতু শেলটি সেই বিকল্পগুলি দিয়ে শুরু হয় since , শেলটি মূল থেকে স্ক্রিপ্টের নামটি বিশ্লেষণের চেষ্টা না করার কারণ হিসাবে এটি আপত্তিজনক ছিল এবং এইভাবে আপত্তিজনক থেকে যায় কারণ সামঞ্জস্যতার কারণে আচরণটি আধুনিক বোর্ন-লাইকগুলিতে বজায় থাকে। আমি যদি আমার সমস্ত বোর্নের ইতিহাস এবং বহনযোগ্যতার ট্রিভিয়া ঠিক মনে রাখি।
mtraceur

0

সংক্ষিপ্ত উত্তর: এটি দোভাষীর পথ।

সম্পাদনা (দীর্ঘ উত্তর): "নোড" এর আগে কোনও স্ল্যাশ না হওয়ার কারণ হ'ল আপনি সর্বদা #! / বিন / এর নির্ভরযোগ্যতার গ্যারান্টি দিতে পারবেন না। "/ Env" বিট পরিবর্তিত পরিবেশে স্ক্রিপ্ট চালিয়ে প্রোগ্রামটিকে আরও ক্রস-প্ল্যাটফর্ম করে তোলে এবং আরও নির্ভরযোগ্যভাবে দোভাষী প্রোগ্রামটি সন্ধান করতে সক্ষম হয়।

আপনার অগত্যা এটির প্রয়োজন নেই, তবে বহনযোগ্যতা (এবং পেশাদারিত্ব) নিশ্চিত করতে এটি ব্যবহার করা ভাল is


1
/usr/bin/envবিট পরিবেশ পরিবর্তন করে না। এটি (বেশিরভাগ) পরিচিত স্থানে কেবল একটি কমান্ড যা আর্গুমেন্ট হিসাবে দেওয়া অন্য কমান্ডকে আহ্বান করে এবং $PATHএটি অনুসন্ধান করার জন্য অনুসন্ধান করে। মুল বক্তব্যটি হ'ল #!লাইনটি কমান্ডটি চালিত হওয়ার জন্য পুরো পথের প্রয়োজন এবং আপনি কোথায় জানেন না তা অগত্যা node
কিথ থমসন

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