क्या बिना उद्धरणों के इको चलाना खतरनाक है?


11

मैंने कुछ इसी तरह के विषयों को देखा है, लेकिन वे चर को उद्धृत नहीं करने की बात कर रहे हैं, जो मुझे पता है कि अवांछित परिणाम हो सकते हैं।

मैंने इस कोड को देखा और सोच रहा था कि क्या यह संभव हो सकता है कि जब कोड की यह लाइन निष्पादित हो, तो इसे चलाया जा सके।

echo run after_bundle


मैं इस समय भाग गया जब मेरे पास था: लक्ष्य = "*** लाइव सर्वर ***"; इको लक्ष्य: $ लक्ष्य; और *** एक फ़ोल्डर लिस्टिंग में विस्तारित ... 😬
मैट पार्किंस

जवाबों:


17

विशिष्ट मामले के लिए

echo run after_bundle

उद्धृत करने की आवश्यकता नहीं है। कोई उद्धरण की आवश्यकता नहीं है क्योंकि तर्क echoस्थिर तार हैं जिनमें कोई चर विस्तार या कमांड प्रतिस्थापन आदि नहीं हैं। वे "सिर्फ दो शब्द" हैं (और जैसा कि स्टीफन बताते हैं , वे अतिरिक्त रूप से पोर्टेबल वर्ण सेट से बाहर निर्मित होते हैं )।

"खतरे" तब आता है जब आप चर डेटा से निपटते हैं जो शेल का विस्तार या व्याख्या कर सकता है। ऐसे मामलों में, इस बात का ध्यान रखा जाना चाहिए कि शेल सही काम करता है और इसका परिणाम वही होता है जो अभीष्ट है।

निम्नलिखित दो प्रश्नों के बारे में प्रासंगिक जानकारी है:


echoकभी-कभी इस साइट पर उत्तरों में संभावित हानिकारक आदेशों की "रक्षा" करने के लिए उपयोग किया जाता है। उदाहरण के लिए, मैं दिखा सकता हूं कि फ़ाइलों को कैसे हटाया जाए या फ़ाइलों को उपयोग करके एक नए गंतव्य पर ले जाया जाए

echo rm "${name##*/}.txt"

या

echo mv "$name" "/new_dir/$newname"

यह वास्तव में फ़ाइलों को हटाने या नाम बदलने के बजाय टर्मिनल पर कमांड का उत्पादन करेगा। उपयोगकर्ता तब आदेशों का निरीक्षण कर सकता है, यह तय कर सकता है कि वे ठीक लग रहे हैं, echoफिर से हटाएं और फिर से चलाएं।

आपका आदेश echo run after_bundleउपयोगकर्ता के लिए एक निर्देश हो सकता है, या यह एक "टिप्पणी" कोड का टुकड़ा हो सकता है जो परिणामों को जाने बिना चलाने के लिए बहुत खतरनाक है।

echoइस तरह का उपयोग करते हुए , किसी को यह जानना होगा कि संशोधित आदेश क्या करता है और किसी को यह गारंटी देनी चाहिए कि संशोधित आदेश वास्तव में सुरक्षित है (यह संभवतः ऐसा नहीं होगा यदि इसमें पुनर्निर्देशन शामिल है, और पाइप लाइन पर इसका उपयोग करना काम नहीं करता है, आदि)


उद्धरण जोड़ना यह जानने के लिए पर्याप्त नहीं है कि एक शेल क्या करेगा, हालांकि - जैसा कि आप बता नहीं सकते कि echo rm "first file.txt" "second file.txt"किसी भी तरह से अलग है echo rm "first" "file.txt" "second" "file.txt", दोनों से आउटपुट समान है। यदि आप एक शेल कमांड को आउटपुट के रूप में जनरेट करना चाहते हैं, तो एक का उपयोग करना होगाprintf '%q ' rm "first file.txt" "second file.txt"; echo या कुछ समतुल्य होना चाहिए जो सिंटैक्टिक कोट्स को पुन: उत्पन्न करता है जो argvपारित होने का मूल्यांकन करता है ।
चार्ल्स डफी

@CharlesDuffy मैं वास्तव में किसी को भी कॉपी-पेस्ट डिबगिंग आउटपुट की उम्मीद नहीं करता और इसे शेल में चलाता हूं!
Kusalananda

1
शेल कमांड बनाना और फिर उन्हें पाइप करना shबिल्कुल असामान्य पैटर्न नहीं है, और लोगों को यह पूछते हुए देखकर " fooमैं कमांड लाइन पर इसे चलाने पर काम क्यों करता है , लेकिन यह स्क्रिप्ट जो echoलाइन के सामने उस सटीक स्ट्रिंग का उत्सर्जन नहीं करता है?" " यहाँ हर समय होता है। यदि यह आपके बग्स को छुपाता है - तो बिंदु से अधिक, डिबगिंग आउटपुट सहायक नहीं है - और यदि आपके बग उद्धरण से संबंधित हैं, तो echoउन्हें प्रकट नहीं करेंगे।
चार्ल्स डफी

27

सिर्फ कुसलानंद के ठीक जवाब के ऊपर एक अतिरिक्त नोट ।

echo run after_bundle

ठीक है क्योंकि उन 3 तर्कों में से कोई भी वर्ण उन echoवर्णों को सम्‍मिलित नहीं करता है जो शेल के लिए विशेष हैं।

और (अतिरिक्त बिंदु जो मैं यहां बनाना चाहता हूं) कोई सिस्टम लोकेल नहीं है जहां उन बाइट्स उन अक्षरों में अनुवाद कर सकें जो शेल के लिए विशेष हैं।

उन सभी पात्रों में हैं जो POSIX पोर्टेबल चरित्र सेट को कॉल करते हैं । उन वर्णों को मौजूद होना चाहिए और POSIX system and पर सभी वर्ण सेटों में समान कूटबद्ध किया जाना चाहिए।

ताकि कमांड लाइन की व्याख्या स्थानीय लोगों की परवाह किए बिना की जाएगी।

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

उदाहरण के लिए UTF-8 में:

echo voilà | iconv -f UTF-8 -t //TRANSLIT

यह à0xc3 0xa0 के रूप में एन्कोडेड है। अब, यदि आपके पास शेल स्क्रिप्ट में कोड की एक पंक्ति है और शेल स्क्रिप्ट को एक उपयोगकर्ता द्वारा उपयोग किया जाता है, जो एक लोकेल का उपयोग करता है, जिसका चार्ट UTF-8 नहीं है, तो वे दो बाइट्स बहुत भिन्न वर्ण बना सकते हैं।

उदाहरण के लिए, एक fr_FR.ISO8859-15स्थानीय भाषा में, मानक सिंगल-बाइट वर्णसेट का उपयोग करते हुए एक सामान्य फ्रांसीसी लोकेल, जो फ्रांसीसी भाषा को शामिल करता है (अंग्रेजी सहित अधिकांश पश्चिमी यूरोपीय भाषाओं के लिए उपयोग किया जाता है), कि 0xc3 बाइट को Ãचरित्र के रूप में व्याख्या किया गया है और 0xa2 गैर के रूप में है अंतरिक्ष चरित्र को तोड़ना।

और NetBSD³ जैसी कुछ प्रणालियों पर, उस गैर-ब्रेकिंग स्पेस को एक खाली वर्ण के रूप में माना जाता है ( isblank()यह सच है, यह मेल खाता है [[:blank:]]) और गोले bashइसलिए इसे अपने सिंटैक्स में एक टोकन सीमांकक के रूप में मानते हैं।

इसका मतलब है कि तर्क के echoसाथ चलने के बजाय $'voil\xc3\xa0', वे इसे $'voil\xc3'तर्क के रूप में चलाते हैं , जिसका अर्थ है कि यह voilàसही तरीके से प्रिंट नहीं होगा ।

यह बिग 5, बिग5-एचकेएससीएस, GB18030, GBK की तरह चीनी वर्ण सेट जो कई पात्रों जिसका एन्कोडिंग के रूप में समान कूट शामिल है के साथ एक बहुत खराब हो जाता है |, `, \(यह भी है कि ऊटपटांग SJIS (सबसे खराब नाम के लिए), माइक्रोसॉफ्ट कांजी उर्फ, सिवाय ¥इसके बजाय यह है \, लेकिन अभी भी \अधिकांश उपकरणों के रूप में माना जाता है क्योंकि यह 0x5c के रूप में एन्कोडेड है)।

उदाहरण के लिए, यदि एक zh_CN.gb18030चीनी लोकेल में, आप एक स्क्रिप्ट लिखते हैं जैसे:

echo  reboot

वह स्क्रिप्ट 詜 rebootGB18030 या GBK का उपयोग कर एक लोकल में आउटपुट करेगा 唰 reboot, BIG5 या BIG5-HKSCS का उपयोग करते हुए, लेकिन ASCII या ISO8859-15 या UTF-8 का उपयोग करते हुए एक लोकेल में, rebootचलाने का कारण होगा क्योंकि GB18030 एन्कोडिंग का 0xd4 0x7c है और 0x7c |ASCII का एन्कोडिंग है इसलिए हम रनिंग को समाप्त करते हैं:

 echo �| reboot

(यह कि का प्रतिनिधित्व हालांकि 0xd4 बाइट को लोकेल में प्रस्तुत किया गया है)। unameइसके बजाय कम हानिकारक का उपयोग करके उदाहरण reboot:

$ echo $'echo \u8a5c uname' | iconv -t gb18030 > myscript
$ LC_ALL=zh_CN.gb18030 bash ./myscript | sed -n l
\324| uname$
$ LC_ALL=C bash ./myscript | sed -n l
Linux$

( unameचलाया गया था)।

इसलिए मेरी सलाह होगी कि उन सभी तारों को उद्धृत किया जाए, जिनमें पोर्टेबल चरित्र सेट के बाहर के पात्र हों।

हालांकि ध्यान दें, चूंकि की एन्कोडिंग \और `उन पात्रों में से कुछ की एन्कोडिंग में पाए जाते हैं, यह बेहतर नहीं उपयोग करने के लिए है \या "..."या $'...'(अंदर जो `और / या \अभी भी विशेष कर रहे हैं), लेकिन '...'बजाय पोर्टेबल वर्ण सेट के बाहर पात्रों उद्धृत करने के लिए।

मुझे ऐसी किसी भी प्रणाली के बारे में पता नहीं है, जिसमें एक स्थान है जहां चारसेट का कोई भी चरित्र है ( 'निश्चित रूप से स्वयं के अलावा ) जिसकी एन्कोडिंग में एन्कोडिंग है ', इसलिए उन्हें '...'निश्चित रूप से सबसे सुरक्षित होना चाहिए।

ध्यान दें कि कई गोले भी $'\uXXXX'यूनिकोड कोड बिंदु के आधार पर वर्णों को व्यक्त करने के लिए एक संकेतन का समर्थन करते हैं । जैसे गोले में zshऔर bash, चरित्र को लोकेल के चारसेट में एन्कोड किया गया होता है (हालांकि उस चरित्र में अप्रत्याशित व्यवहार नहीं हो सकता है अगर उस चरित्र में ऐसा नहीं है)। इससे आप अपने शेल कोड में गैर-एएससीआईआई अक्षर डालने से बच सकते हैं।

तो ऊपर:

echo 'voilà' | iconv -f UTF-8 -t //TRANSLIT
echo '詜 reboot'

या:

echo $'voil\u00e0'
echo $'\u8a5c reboot'

(चेतावनी के साथ यह स्क्रिप्ट को तोड़ सकता है जब उन स्थानों पर चलाए जा सकते हैं जिनमें वे वर्ण नहीं हैं)।

या बेहतर है, क्योंकि \यह भी विशेष echo(या कम से कम कुछ echo कार्यान्वयन, कम से कम यूनिक्स के अनुरूप हैं):

printf '%s\n' 'voilà' | iconv -f UTF-8 -t //TRANSLIT
printf '%s\n' '詜 reboot'

(ध्यान दें कि \पहले तर्क में भी विशेष है printf, इसलिए गैर-एएससीआईआई पात्रों को वहां से बचना बेहतर होता है, क्योंकि उनमें एन्कोडिंग हो सकती है \)।

ध्यान दें कि आप भी कर सकते हैं:

'echo' 'voilà' | 'iconv' '-f' 'UTF-8' '-t' '//TRANSLIT'

(यह ओवरकिल होगा लेकिन अगर आप यह सुनिश्चित नहीं कर पा रहे हैं कि पोर्टेबल कैरेक्टर सेट में कौन से अक्षर हैं तो आप निश्चित नहीं हैं)

यह भी सुनिश्चित करें कि `...`कमांड प्रतिस्थापन के प्राचीन रूप का उपयोग न करें (जो बैकस्लैश प्रसंस्करण के अन्य स्तर का परिचय देता है), लेकिन $(...)इसके बजाय का उपयोग करें ।


¹ तकनीकी तौर पर, echoयह भी करने के लिए तर्क के रूप में पारित हो जाता है echoउपयोगिता (यह बताने के लिए कि यह कैसे लागू किया गया था), यह argv[0]और argcहै, हालांकि अधिकांश गोले में आजकल 3 echobuiltin है, ताकि exec()एक के /bin/echo3 तर्कों की सूची के साथ फ़ाइल से प्रेरित है खोल। तर्कों की सूची पर विचार करना आम बात है क्योंकि दूसरे के साथ शुरू होने वाली ( argv[1]से argv[argc - 1]) के रूप में यह है कि कमांड मुख्य रूप से कार्य करते हैं।

Systems ja_JP.SJISFreeBSD सिस्टम के आकर्षक स्थानीय होने के लिए एक उल्लेखनीय अपवाद है जिसके वर्ण में \न तो कोई ~चरित्र है और न ही !

³ ध्यान दें कि जबकि कई सिस्टम (FreeBSD, Solaris, GNU वाले नहीं) हालांकि U + 00A0 को [[:blank:]]UTF-8 स्थानों में मानते हैं, कुछ अन्य स्थानों में जैसे ISO8859-15 का उपयोग करने वाले लोग करते हैं, संभवतः इस तरह के मुद्दे से बचते हैं।


अपने पहले पैराग्राफ में, आप हमें बताते हैं ... "उन 3 तर्कों में से वर्णों के पास echo...", मैं केवल 2 तर्क गिनता हूं जो कमांड में पारित किए जा echoरहे हैं, जिन तर्कों को मैं गिन सकता हूं runऔर after_bundle, आप कैसे समझाते हैं गिना गया और 3 तर्क मिले?
फेरीबिग

1
@ViktorFonic, तर्कों की संख्या के बारे में संपादन देखें (और मुख्य समस्या यह नहीं है echo)। (exec -a foo /bin/echo --help)जीएनयू सिस्टम पर देखें और जीएनयू शेल के साथ /bin/echoउपयोगिता के लिए एक मनमाना पहला तर्क कैसे पारित करें ।
स्टीफन चेज़लस

@Ferrybig स्टीफन का संपादन देखें, फुटनोट 1. सामान्य C शैली में कमांड करने के लिए तर्क तर्क की सरणी हैं, argv [0] के साथ ही निष्पादन योग्य नाम है। किंड $0गोले में स्थित और स्थितीय मापदंडों के समान है ।
सर्गी कोलोडियाज़नी

373 एन्कोडिंग हैं iconv, जिसमें ESCपरिवर्तित किया जाता है '। प्रयास करें (एक उदाहरण के रूप में):printf '\x1b'|iconv -f utf8 -t IBM-937|xxd
आइजैक

173 एन्कोडिंग हैं जिनमें कुछ कोडपॉइंट (ESC के अलावा) को a में परिवर्तित किया जाता है '। कोशिश करो printf '\u2804' | iconv -f utf8 -t BRF | xxd। ऐसे एन्कोडिंग हैं जिनमें बहुत सारे कोडप्वाइंट हैं जो बन जाते हैं '। UCS-4 में लगभग 8695 कोडपॉइंट बन जाते हैं '। कोशिश करो printf '\U627' | iconv -cf utf-8 -t UCS-4। कई (37) एन्कोडिंग वर्ण 0x127 को a में बदलते हैं '। कोशिश करेंprintf '\U127' | iconv -cf utf8 -t UCS2 |xxd
इसहाक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.