लूप के लिए "तर्क बहुत लंबा" त्रुटि क्यों नहीं बढ़ाता है?


9

मैंने पाया कि यह "तर्क बहुत लंबा" त्रुटि को बढ़ाएगा:

ls *.*

और यह इसे नहीं बढ़ाएगा:

for file in *.*
do
    echo $file
done

क्यों?


क्या आपने दोनों प्रयोगों में समान शेल का उपयोग किया था? शायद /bin/bashबनाम /bin/sh(जो कि शायद डैश का लिंक है)?
मैक्सक्लेपज़िग

हां, मैंने फ़ाइल नाम के साथ 10000 फाइलों के साथ प्रयोग किया है जो काफी लंबे हैं। "ls *" विफल रहा और "f in *" सफल रहा।
lamwaiman1988

जवाबों:


13

"तर्क बहुत लंबा" त्रुटि है E2BIG, execveसिस्टम कॉल द्वारा उठाया जाता है यदि तर्कों का कुल आकार (प्लस सिस्टम पर पर्यावरण,) बहुत बड़ा है। execveकॉल एक है कि बाहरी प्रक्रियाओं शुरू होता है, विशेष रूप से एक अलग निष्पादन योग्य फ़ाइल लोड हो रहा है (वहाँ एक अलग कॉल है, fork, एक अलग प्रक्रिया है जिसका कोड एक ही निष्पादन योग्य फ़ाइल से अब भी है चलाने के लिए)। forतो यह बुला शामिल नहीं करता है पाश, एक आंतरिक खोल निर्माण है execvels *.*जब गोला का विस्तार होता है, लेकिन जब lsकॉल किया जाता है , तो कमांड एरर उठाती है।

execveत्रुटि के साथ विफल रहता है E2BIGजब कमांड का कुल आकार ARG_MAX सीमा से बड़ा होता है । आप अपने सिस्टम पर कमांड के साथ इस सीमा का मूल्य देख सकते हैं getconf ARG_MAX। (यह संभव है कि आप इस सीमा पर जा सकते हैं यदि आपके पास पर्याप्त मेमोरी है, तो ARG_MAXगारंटी के तहत रखना execveजब तक कोई असंबंधित काम नहीं करेगा।)


और शेल की सीमा क्यों नहीं थी?
lamwaiman1988

1
@ gunbuster363 execveकर्नेल द्वारा सीमा को लागू किया जाता है, यह सीमाएं डालता है क्योंकि तर्क को एक बिंदु पर कर्नेल मेमोरी के माध्यम से कॉपी करने की आवश्यकता होती है और उपयोगकर्ता प्रक्रियाओं को शेल मेमोरी की एक मनमानी राशि का अनुरोध करने की अनुमति नहीं दी जा सकती है। शेल के अंदर, कोई सीमा नहीं है, वर्चुअल मेमोरी में फिट होने वाली कोई भी चीज ठीक नहीं है।
गिल्स एसओ- बुराई को रोकना '

5

मुझे लगता है कि पहले उदाहरण lsमें / जोड़ी सिस्टम कॉल के bashमाध्यम से निष्पादित किया जाता है , दूसरे में, सभी कामकाज आंतरिक हैं ।forkexecbash

execकॉल सीमा नहीं होती, के आंतरिक कार्य bash(बेहतर या, अलग सीमा के साथ कुछ नहीं करना है कि बजाय नहीं है exec, शायद उपलब्ध स्मृति की मात्रा)।


आप करने के लिए सीमा पा सकते हैं execमें /usr/include/linux/limits.hआम तौर पर, के रूप में परिभाषित ARG_MAX
jw013

यदि हम लूप के लिए शेल का उपयोग करते हैं, तो क्या आपको लगता है कि आइटम की एक बड़ी सूची सभी रैम का उपभोग करेगी?
lamwaiman1988

यह उत्तर गलत है। यह 'आंतरिक' नहीं है यह सिर्फ इतना है कि तर्कों और आदेशों की सीमाएं अलग हैं।
बहुपद

5

क्योंकि इसके मामले में lsएक तर्क है, और तर्कों की संख्या सीमित है।

forचक्र के मामले में , यह केवल वस्तुओं की एक सूची है। उसके लिए कोई सीमा नहीं है (जहाँ तक मैं जानता हूँ)।


शेल विस्तार के लिए निश्चित रूप से एक सीमा है। यह बहुत अधिक संबंधित है कि आपके पास कितनी रैम उपलब्ध है .. यह कोशिश करें; मेरा 4GB RAM सिस्टम एक गैस्केट को लगभग 15.2 मिलियन 8-बाइट for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
आर्ग से उड़ा देता है

4
@ यदि मुझे वास्तव में यह नहीं लगता कि एक सीमा के रूप में रैम का उल्लेख करना आवश्यक है।
12:मोन तोथ

2
इसकी आवश्यकता नहीं हो सकती है, लेकिन यह टिप्पणियों की प्रकृति है .. किसी को यह दिलचस्प लग सकता है, या मूल्य का भी।
पीटर।

@fred: वास्तव में हाँ, यदि बहुत बड़े तर्कों का विस्तार करना एक आम समस्या थी, तो इसे याद में सब कुछ रखे बिना इसे लागू करना संभव होगा।
मट्टियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.