`कर्ल के बीच क्या अंतर है? sh` और `श -c” $ (कर्ल) ”`?


23

डॉकर के लिए एक आसान स्थापित विधि (उदाहरण के लिए) यह है:

curl -sSL https://get.docker.com/ | sh

हालाँकि, मैंने कुछ ऐसे भी देखे हैं जो इस तरह दिखते हैं (डॉकर उदाहरण का उपयोग करते हुए):

sh -c "$(curl -sSL https://get.docker.com/)"

वे कार्यात्मक रूप से समान दिखाई देते हैं, लेकिन क्या एक के बाद एक का उपयोग करने का कारण है? या यह सिर्फ एक प्राथमिकता / सौंदर्य की बात है?

(ध्यान दें, अज्ञात मूल से स्क्रिप्ट चलाते समय बहुत सावधान रहें।)

जवाबों:


39

व्यावहारिक अंतर है।

curl -sSL https://get.docker.com/ | shशुरू होता है curlऔर shएक ही समय में, curlके इनपुट के साथ आउटपुट को जोड़ता है sh। स्क्रिप्ट को चला सकते हैं curlजितनी तेजी से (लगभग) डाउनलोड के साथ बाहर ले जाएगा sh। सर्वर समय में अनियमितताओं का पता लगा सकता है और दुर्भावनापूर्ण कोड को इंजेक्ट नहीं कर सकता है, बस संसाधन को किसी फ़ाइल या बफर में डाउनलोड करते समय या ब्राउज़र में देखने पर दिखाई नहीं देता है।

में sh -c "$(curl -sSL https://get.docker.com/)", curlचलाने से पहले सख्ती से shचलाया जाता है। संसाधन की पूरी सामग्री डाउनलोड होने से पहले आपके शेल में डाउनलोड और पास हो shजाती है। आपका शेल केवल तभी शुरू होता है shजब curlवह बाहर निकल चुका होता है , और संसाधन के पाठ को उसमें पास करता है। सर्वर shकॉल का पता नहीं लगा सकता है ; कनेक्शन समाप्त होने के बाद ही इसे शुरू किया जाता है। यह स्क्रिप्ट को पहले किसी फ़ाइल में डाउनलोड करने के समान है।

(यह डॉकटर मामले में प्रासंगिक नहीं हो सकता है, लेकिन यह सामान्य रूप से एक समस्या हो सकती है और दोनों कमांड के बीच व्यावहारिक अंतर को उजागर करता है।)


2
धन्यवाद, यह दोनों के बीच सबसे महत्वपूर्ण अंतर जैसा लगता है।
सरके

क्या आप कृपया इस दावे का समर्थन करते हुए संसाधन का हवाला दे सकते हैं? मुझे यह जानने में बहुत दिलचस्पी होगी कि सर्वर 'श' कॉल का पता कैसे लगा सकता है।
अल्फ्रेड आर्मस्ट्रांग

1
@AlfredArmstrong Uhm, मैंने vulnerable to server-side detectionवाक्यांश पर एक लिंक डाला । यह एक ब्लॉग पोस्ट की ओर जाता है जो महान विस्तार से बताता है कि वे इसे कैसे प्राप्त करते हैं। टीएल; डीआर: अपनी स्क्रिप्ट में नींद डालें और सर्वर पर रिसेप्शन में देरी का निरीक्षण करें।
जोनास श्फर

1
@JonasWielicki धन्यवाद - लिंक बहुत स्पष्ट नहीं था - आपकी गलती नहीं, एसई के सीएसएस के नीचे मुझे लगता है। लोग शानदार ढंग से डरपोक हैं, क्या वे नहीं हैं? :)
अल्फ्रेड आर्मस्ट्रांग

1
सभी मुझे आश्चर्यचकित करते हैं कि अगर किसी ने कभी भी उस चाल को वास्तविकता में पकड़ने की कोशिश की है, तो तुरंत पकड़े बिना। ऐसा नहीं है कि यह संभवत: बहुत मायने रखता है क्योंकि आप शायद स्क्रिप्ट को इस तरह की चाल के बिना भी कुछ दुर्भावनापूर्ण कर सकते हैं, और जो कोई भी इसे पूरी तरह से नहीं पढ़ता है वह कमजोर होगा।
ilkkachu

11

मेरा मानना ​​है कि वे व्यावहारिक रूप से समान हैं। हालांकि, ऐसे दुर्लभ मामले हैं जहां वे अलग हैं।

$(cmd) के परिणामों के साथ प्रतिस्थापित किया जाता है cmd । उस परिणाम कमांड की लंबाई अधिकतम तर्क लंबाई मान से अधिक होनी चाहिए getconf ARG_MAX, यह परिणाम को छोटा कर देगा, जिसके परिणामस्वरूप अप्रत्याशित परिणाम हो सकते हैं।

पाइप विकल्प में यह सीमा नहीं है। curlकमांड से आउटपुट की प्रत्येक लाइन bashको पाइप से आने पर निष्पादित किया जाएगा ।

लेकिन ARG_MAX आमतौर पर 256,000 वर्ण श्रेणी में होता है। एक डॉकटर इंस्टॉल के लिए, मुझे या तो विधि का उपयोग करने पर विश्वास होगा। :-)


दिलचस्प है, इसलिए एक अंतर है। धन्यवाद
Sarke

1
जब संदेह हो, तो पाइप विधि का उपयोग करें। मैंने अपने उत्तर में वरीयता निर्दिष्ट नहीं की, लेकिन मैं इस तरह के उपयोग के लिए पाइप विधि को प्राथमिकता दूंगा क्योंकि आप कभी नहीं जानते कि पाइप के माध्यम से कितना डेटा आ रहा है।
ग्रेग टार्सा

2
"यह परिणाम को छोटा कर देगा" - शेल को उसके लिए एक त्रुटि संदेश जारी करना चाहिए, न कि चुपचाप काट देना चाहिए। परीक्षण करते समय, मुझे नीचे के शेल से भी त्रुटि मिलती है ARG_MAX, bash अपने सिस्टम पर 131072 बाइट्स के लिए एक व्यक्तिगत तर्क को सीमित करता है, जब getconf ARG_MAXप्रिंट करता है 2097152। लेकिन या तो रास्ता, त्रुटि या छंटनी, यह काम नहीं करेगा।
hvd

लेकिन बॉर्न शेल के पुराने कार्यान्वयन में बहुत कम सीमाएं थीं। 4.2BSD में यह सीमा 10240 अक्षर थी, और पहले के सिस्टम पर यह और भी कम थी। अगर मुझे सही से याद है, तो इन शुरुआती गोले में से कुछ ने चुपचाप छंटनी की।
एंडी

एक तर्क के लिए 128 kB की सीमा एक लिनक्स चीज है, यह बैश के बारे में नहीं है।
ilkachachu

8

इन curl -sSL https://get.docker.com/ | sh:

  • दोनों आदेश, curlऔर sh, एक ही समय में, संबंधित उपधाराओं में शुरू होंगे

  • से STDOUT curlको STDIN के रूप में पारित किया जाएगा sh(यह वह है जो पाइप |,, करता है)

जबकि sh -c "$(curl -sSL https://get.docker.com/)":

  • कमांड प्रतिस्थापन, $()को पहले निष्पादित curlकिया जाएगा अर्थात पहले एक सबहेल में चलाया जाएगा

  • कमांड प्रतिस्थापन, $()को STDOUT से बदल दिया जाएगाcurl

  • sh -c (गैर-इंटरैक्टिव, गैर-लॉगिन शेल) से STDOUT को निष्पादित करेगा curl


1
तो, क्या कोई वास्तविक अंतर है?
सरके

@ सर्के हां, सैद्धांतिक रूप से जैसा मैंने उल्लेख किया है, लेकिन व्यावहारिक रूप से शायद ही ध्यान देने योग्य है। (यदि आप कमांड प्रतिस्थापन को
निर्विवाद

1
@ सर्के, अगर स्क्रिप्ट पूरी तरह से डाउनलोड नहीं होती है, तो आप इसे पाइपिंग के साथ जरूरी नहीं समझेंगे। इस प्रक्रिया को नजरअंदाज किया जा सकता है।
Janus Troelsen

@JanusTroelsen आपके पास पूरी तरह से डाउनलोड नहीं होने का क्या मतलब है? ऐसा क्यों होता है कि सर्वर त्रुटि के अलावा जिस स्थिति में कुछ भी करने के लिए पाइप नहीं होगा।
हैफेल

या कनेक्शन रुकावट ... वहाँ कई तरीके हैं एक हस्तांतरण विफल हो सकता है
Janus Troelsen

0

दोनों के बीच एक अंतर (वेब ​​पर अन्य उत्तरों से लिया गया) यह है कि यदि आप एक ही बार में पूरी स्क्रिप्ट डाउनलोड नहीं करते हैं, तो यह एक अज्ञात बिंदु पर स्क्रिप्ट के माध्यम से आधे रास्ते को काट सकता है और कमांड का अर्थ बदल सकता है मार डाला। इसलिए ऐसा लगता है कि पहले पूरी फाइल को डाउनलोड किया जाए और फिर उसका मूल्यांकन करना बेहतर होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.