"तर्क सूची बहुत लंबी है": मैं अपनी कमान बदले बिना, इससे कैसे निपटूं?


18

जब मैं एक कमांड चलाता हूं ls */*/*/*/*.jpg, तो मुझे त्रुटि मिलती है

-bash: /bin/ls: Argument list too long

मुझे पता है कि ऐसा क्यों होता है: ऐसा इसलिए है क्योंकि कमांड के लिए तर्कों के लिए स्थान की मात्रा पर कर्नेल सीमा होती है। मानक सलाह यह है कि मैं जिस कमांड का उपयोग करता हूं उसे बदलने के लिए, तर्क के लिए इतनी जगह की आवश्यकता से बचने के लिए (जैसे, उपयोग findऔर xargs)।

क्या होगा अगर मैं कमांड नहीं बदलना चाहता हूँ? क्या होगा यदि मैं उसी कमांड का उपयोग करना चाहता हूं? मैं इस त्रुटि को प्राप्त किए बिना चीजों को "बस काम" कैसे बना सकता हूं? क्या समाधान उपलब्ध हैं?


उपयोगी रीडिंग: बैश FAQ 95 । अपनी कमांड को बदले बिना आप अपनी तर्क सूची को अधिकतम आकार बढ़ाने, या अपनी निर्देशिका संरचना को बदलने के लिए पुन: जमा करने के अलावा बहुत कुछ नहीं कर सकते हैं ताकि कम फाइलें हों।
jw013

1
@ jw013 लिनक्स कर्नेल संस्करण के आधार पर तर्क सूची को बढ़ाना संभव हो सकता है - हाल ही में सिस्टम में बदलाव के बारे में जानकारी के लिए unix.stackexchange.com/a/45161/8979 देखें ।
उलरिच डैंगेल

@UlrichDangel, हाँ, यह संभव है! मेरा जवाब देखिए; मेरा जवाब दिखाता है कि यह कैसे करना है (लिनक्स पर, हाल ही में पर्याप्त कर्नेल के साथ)।
डीडब्ल्यू

जवाबों:


27

लिनक्स पर, कमांड तर्कों के लिए अधिकतम स्थान उपलब्ध स्टैक स्थान की मात्रा का 1 / 4th है। तो, एक समाधान स्टैक के लिए उपलब्ध स्थान की मात्रा में वृद्धि करना है।

लघु संस्करण: जैसे कुछ चलाते हैं

ulimit -s 65536

लंबा संस्करण: स्टैक के लिए उपलब्ध स्थान की डिफ़ॉल्ट राशि 8192 KB जैसी है। आप निम्नानुसार उपलब्ध स्थान की मात्रा देख सकते हैं:

$ ulimit -s
8192

एक बड़ी संख्या चुनें, और स्टैक के लिए उपलब्ध स्थान की मात्रा निर्धारित करें। उदाहरण के लिए, यदि आप स्टैक के लिए 65536 KB तक की अनुमति देना चाहते हैं, तो इसे चलाएं:

$ ulimit -s 65536

आपको ट्रायल-एंड-एरर का उपयोग करके इसे कितना बड़ा होना चाहिए, इसके साथ खेलने की आवश्यकता हो सकती है। कई मामलों में, यह एक त्वरित और गंदे समाधान की वाक्य रचना बाहर आदेश और काम को संशोधित करने की आवश्यकता को समाप्त होगा find, xargsआदि (हालांकि मुझे लगता है ऐसा करने के लिए अन्य लाभ कर रहे हैं)।

मेरा मानना ​​है कि यह लिनक्स-विशिष्ट है। मुझे संदेह है कि यह शायद किसी अन्य यूनिक्स ऑपरेटिंग सिस्टम (परीक्षण नहीं) पर मदद नहीं करेगा।


1
आप इस तरह से सत्यापित कर सकते हैं कि इसने काम किया: $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
एलेक्स

3

यह लिनक्स जर्नल लेख 4 समाधान देता है। केवल चौथे समाधान में कमांड को बदलना शामिल नहीं है:

विधि # 4 में मैन्युअल रूप से उन पेजों की संख्या बढ़ाना शामिल है जो कमांड-लाइन तर्कों के लिए कर्नेल के भीतर आवंटित किए गए हैं। यदि आप शामिल / linux / binfmts.h फ़ाइल को देखते हैं, तो आपको निम्नलिखित शीर्ष के पास मिलेगा:

/*
 * MAX_ARG_PAGES defines the number of pages allocated for   arguments
 * and envelope for the new program. 32 should suffice, this gives
 * a maximum env+arg of 128kB w/4KB pages!
 */
#define MAX_ARG_PAGES 32

कमांड-लाइन तर्कों को समर्पित मेमोरी की मात्रा बढ़ाने के लिए, आपको बस MAX_ARG_PAGES मान अधिक संख्या के साथ प्रदान करना होगा। एक बार जब यह संपादन सहेज लिया जाता है, तो आप नए कर्नेल में सामान्य रूप से करते हैं, बस पुन: स्थापित, स्थापित करें और रिबूट करें।

अपने स्वयं के परीक्षण प्रणाली पर मैंने इस मूल्य को 64 तक बढ़ाकर अपनी सभी समस्याओं को हल करने में कामयाब रहा। व्यापक परीक्षण के बाद, मैंने स्विच के बाद से एक भी समस्या का अनुभव नहीं किया है। यह पूरी तरह से अपेक्षित है, यहां तक ​​कि MAX_ARG_PAGES64 के सेट के साथ भी , सबसे लंबे समय तक संभव कमांड लाइन जो मैं उत्पादन कर सकता था वह केवल 256KB सिस्टम मेमोरी पर कब्जा कर सकता है - आज के सिस्टम हार्डवेयर मानकों द्वारा बहुत अधिक नहीं।

विधि # 4 के लाभ स्पष्ट हैं। अब आप केवल सामान्य रूप से कमांड चलाने में सक्षम हैं, और यह सफलतापूर्वक पूरा होता है। नुकसान समान रूप से स्पष्ट हैं। यदि आप उपलब्ध सिस्टम मेमोरी की मात्रा से परे कमांड लाइन के लिए उपलब्ध मेमोरी की मात्रा बढ़ाते हैं, तो आप अपने सिस्टम पर एक डॉस हमला कर सकते हैं और इसे क्रैश कर सकते हैं। विशेष रूप से बहुउपयोगकर्ता प्रणालियों पर, यहां तक ​​कि एक छोटी सी वृद्धि का भी महत्वपूर्ण प्रभाव हो सकता है क्योंकि प्रत्येक उपयोगकर्ता को तब अतिरिक्त मेमोरी आवंटित की जाती है। इसलिए हमेशा अपने स्वयं के वातावरण में बड़े पैमाने पर परीक्षण करें, क्योंकि यह निर्धारित करने का सबसे सुरक्षित तरीका है कि क्या विधि # 4 आपके लिए एक व्यवहार्य विकल्प है।

मैं मानता हूं कि सीमा गंभीरता से कष्टप्रद है।


2

इसके बजाय ls */*/*/*/*.jpg, कोशिश करें:

echo */*/*/*/*.jpg | xargs ls

xargs(1) जानता है, सिस्टम पर अधिकतम तर्कों की संख्या क्या है और वह निर्दिष्ट कमांड लाइन को कई बार कॉल करने के लिए अपने मानक इनपुट को तोड़ देगा, उस सीमा से अधिक कोई तर्क नहीं है, चाहे वह जो भी हो (आप इसे उससे कम सेट कर सकते हैं) ओएस ' -nविकल्प का अधिकतम उपयोग करते हुए )।

उदाहरण के लिए, मान लीजिए, सीमा 3 तर्क है और आपके पास पाँच फाइलें हैं। उस मामले में दो बार xargsनिष्पादित lsकिया जाएगा :

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

अक्सर यह पूरी तरह से उपयुक्त है, लेकिन हमेशा नहीं - उदाहरण के लिए, आप पर भरोसा नहीं कर सकते ls(1) छँटाई प्रविष्टियों के सभी आपके लिए ठीक है, क्योंकि प्रत्येक अलग ls-invocation होगा प्रकार केवल द्वारा यह करने के लिए दिया प्रविष्टियों का सबसेट xargs

यद्यपि आप दूसरों द्वारा सुझाई गई सीमा से टकरा सकते हैं, फिर भी एक सीमा होगी - और किसी दिन आपका जेपीजी-संग्रह फिर से आगे निकल जाएगा। अनंत संख्या से निपटने के लिए आपको अपनी स्क्रिप्ट तैयार करनी चाहिए ...


विचार के लिए धन्यवाद! यह कोई बुरा हल नहीं है। दो चेतावनी: 1. यह उन निर्देशिकाओं और फ़ाइलनामों पर विराम लगाता है जिनके नाम में स्थान है, इसलिए यह एक सही विकल्प नहीं है। 2. क्या यह उसी मुद्दे पर चलने वाला है Argument list too long, लेकिन echoइसके बजाय lsगोले पर, जहां echoशेल निर्मित अंतर्देशीय नहीं है? (हो सकता है कि ज्यादातर गोले में यह एक मुद्दा नहीं है, इसलिए शायद यह अप्रासंगिक है।)
डीडब्ल्यू

1
हां, फ़ाइल नाम में विशेष वर्ण एक समस्या है। आपका सबसे अच्छा शर्त यह है findकि -print0विधेय के साथ उपयोग करें - और इसके आउटपुट को विकल्प के xargsसाथ पाइप करें -0echoएक शेल-इन है और exec(3) की कमांड-लाइन सीमा से ग्रस्त नहीं है ।
मिखाइल टी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.