2015-10-10 5 views
5

मुझे "aws sqs" कमांड के तर्क के रूप में 256 केबी पाठ को पास करना होगा, लेकिन 140 केबी पर कमांड लाइन में एक सीमा में चल रहा है। इस पर कई स्थानों पर चर्चा की गई है कि it been solved in the Linux kernel as of 2.6.23 kernelलिनक्स "बहुत सारे तर्क" सीमा को कैसे प्राप्त करें

लेकिन इसे काम पर नहीं मिल सकता है। मैं 3.14.48-33.39.amzn1.x86_64

उपयोग कर रहा हूँ यहां परीक्षण का एक सरल उदाहरण है:

#!/bin/bash 

SIZE=1000 
while [ $SIZE -lt 300000 ] 
do 
    echo "$SIZE" 
    VAR="`head -c $SIZE < /dev/zero | tr '\0' 'a'`" 
    ./foo "$VAR" 
    let SIZE="($SIZE * 20)/19" 
done 

और foo स्क्रिप्ट बस है:

#!/bin/bash 
echo -n "$1" | wc -c 

और मेरे लिए उत्पादन होता है:

117037 
123196 
123196 
129680 
129680 
136505 
./testCL: line 11: ./foo: Argument list too long 
143689 
./testCL: line 11: ./foo: Argument list too long 
151251 
./testCL: line 11: ./foo: Argument list too long 
159211 

तो, सवाल मैं testCL स्क्रिप्ट को कैसे संशोधित कर सकता हूं यह 256 केबी ओ पास कर सकता है एफ डेटा? बीटीडब्ल्यू, मैंने स्क्रिप्ट में ulimit -s 65536 जोड़ने की कोशिश की है और इससे मदद नहीं मिली है।

और अगर यह सादा असंभव मुझे लगता है कि के साथ सौदा कर सकते हैं, लेकिन आप ऊपर

मेरे लिंक से इस उद्धरण पर प्रकाश डाल सकती "लिनक्स 9 की योजना नहीं है, 2.6.23 लिनक्स में चर जोड़ रहा है तर्क की लंबाई। सैद्धांतिक रूप से आपको अक्सर "तर्क सूची बहुत लंबी" त्रुटियों को नहीं मारा जाना चाहिए, लेकिन यह पैच अधिकतम तर्क लंबाई को अधिकतम स्टैक सीमा (ulimit -s) के 25% तक सीमित करता है। "

उत्तर

3

संपादित करें:

मैं अंत में एक भी कमांड लाइन तर्क के रूप में < = 256KB पारित करने में सक्षम था (देखें संपादित करें (4) तल में)। हालांकि, कृपया ध्यान से पढ़ें कि मैंने यह कैसे किया और खुद के लिए फैसला करें कि यह एक तरीका है जिसे आप जाना चाहते हैं। कम से कम आपको यह समझने में सक्षम होना चाहिए कि आप जो भी जानते हैं उससे अन्यथा आप 'अटक गए' क्यों हैं।


ulim -s/4 करने के लिए ARG_MAX के युग्मन के साथ

अधिकतम के रूप में MAX_ARG_STRLEN की शुरूआत आया था। एक तर्क की लंबाई:

/* 
* linux/fs/exec.c 
* 
* Copyright (C) 1991, 1992 Linus Torvalds 
*/ 

...

#ifdef CONFIG_MMU 
/* 
* The nascent bprm->mm is not visible until exec_mmap() but it can 
* use a lot of memory, account these pages in current->mm temporary 
* for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we 
* change the counter back via acct_arg_size(0). 
*/ 

...

static bool valid_arg_len(struct linux_binprm *bprm, long len) 
{ 
return len <= MAX_ARG_STRLEN; 
} 

...

#else 

...

static bool valid_arg_len(struct linux_binprm *bprm, long len) 
{ 
    return len <= bprm->p; 
} 

#endif /* CONFIG_MMU */ 

...

static int copy_strings(int argc, struct user_arg_ptr argv, 
     struct linux_binprm *bprm) 
{ 

...

str = get_user_arg_ptr(argv, argc); 

...

len = strnlen_user(str, MAX_ARG_STRLEN); 
    if (!len) 
     goto out; 

    ret = -E2BIG; 
    if (!valid_arg_len(bprm, len)) 
     goto out; 

...

} 

...

MAX_ARG_STRLENlinux/include/uapi/linux/binfmts.h में के रूप में 32 बार पृष्ठ आकार परिभाषित किया गया है:

...

/* 
* These are the maximum length and maximum number of strings passed to the 
* execve() system call. MAX_ARG_STRLEN is essentially random but serves to 
* prevent the kernel from being unduly impacted by misaddressed pointers. 
* MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer. 
*/ 
#define MAX_ARG_STRLEN (PAGE_SIZE * 32) 
#define MAX_ARG_STRINGS 0x7FFFFFFF 

...

डिफ़ॉल्ट पृष्ठ आकार 4KB ताकि आप तर्क 128KB से अधिक समय से पारित नहीं कर सकते हैं।

अब मैं इसे आजमा नहीं सकता लेकिन शायद आपके सिस्टम पर संभव होने पर विशाल पृष्ठ मोड (पृष्ठ आकार 4 एमबी) पर स्विच करना इस समस्या को हल करता है।

अधिक विस्तृत जानकारी और संदर्भों के लिए this answer से a similar question on Unix & Linux SE देखें।


संपादन:

(1) this answer के अनुसार कर्नेल में n को CONFIG_TRANSPARENT_HUGEPAGE सक्षम करने और CONFIG_TRANSPARENT_HUGEPAGE_MADVISE की स्थापना करके x86_64 लिनक्स 1 एमबी तक के पृष्ठ आकार को बदल सकते हैं config।

(2) ऊपर विन्यास के साथ मेरी कर्नेल फिर कंपाइल करने के बाद बदल जाता getconf PAGESIZE अभी भी रिटर्न 4096. this answerCONFIG_HUGETLB_PAGE भी जरूरी है जो मैं CONFIG_HUGETLBFS के माध्यम से में खींच सकता है के अनुसार। मैं अब recompiling हूँ और फिर परीक्षण करेंगे।

(3) मैं CONFIG_HUGETLBFS सक्षम के साथ अपने कर्नेल फिर कंपाइल और अब /proc/meminfo इसी HugePages_* प्रविष्टियों the corresponding section of the kernel documentation में उल्लेख होता है। हालांकि, getconf PAGESIZE के अनुसार पृष्ठ का आकार अभी भी अपरिवर्तित है। इसलिए जब मुझे mmap कॉल के माध्यम से विशाल पृष्ठों का अनुरोध करने में सक्षम होना चाहिए, तो कर्नेल का डिफ़ॉल्ट पृष्ठ आकार MAX_ARG_STRLEN निर्धारित करने के लिए अभी भी 4 केबी पर तय किया गया है।

(4) मैं #define MAX_ARG_STRLEN (PAGE_SIZE * 64) करने के लिए linux/include/uapi/linux/binfmts.h संशोधित, मेरे गिरी कंपाइल है और अब अपने कोड का उत्पादन:

...

117037 
123196 
123196 
129680 
129680 
136505 
143689 
151251 
159211 

...

227982 
227982 
239981 
239981 
252611 
252611 
265906 
./testCL: line 11: ./foo: Argument list too long 
279901 
./testCL: line 11: ./foo: Argument list too long 
294632 
./testCL: line 11: ./foo: Argument list too long 

तो अब सीमा 128 केबी से 256 केबी तक बढ़ी है। हालांकि मुझे संभावित दुष्प्रभावों के बारे में पता नहीं है। जहां तक ​​मैं कह सकता हूं, मेरा सिस्टम ठीक चल रहा है।

+1

धन्यवाद, यह वही है जो मैं पूछ रहा था। मेरे मामले में इसका अर्थ यह असंभव है (यानी कस्टम कर्नेल नहीं चला सकते हैं) लेकिन यह बहुत उपयोगी है कि मैं अटक गया हूं और जानना ** क्यों **। बीटीडब्ल्यू, त्रुटि संदेश "तर्क सूची बहुत लंबी" गुमराह कर रही है खासकर जब से वह हिस्सा वास्तव में तय किया गया है। इसका एक व्यक्तिगत तर्क का आकार मुद्दा था। – swdev

2

बस कुछ फाइलों में तर्क डालें, और फ़ाइल से "तर्क" स्वीकार करने के लिए अपने प्रोग्राम को संशोधित करें। एक आम सम्मेलन (विशेष रूप से GCC और कई अन्य जीएनयू प्रोग्राम द्वारा उपयोग), @/tmp/arglist.txt की तरह एक तर्क तर्क प्रति एक लाइन

आप शायद लंबे समय तक वातावरण चर के माध्यम से कुछ डेटा पास हो सकता है पूछता है कि फ़ाइल /tmp/arglist.txt से तर्क को पढ़ने के लिए अपने कार्यक्रम, अक्सर है लेकिन वे भी सीमित हैं (और क्या वास्तव में गिरी द्वारा सीमित है, main की प्रारंभिक ढेर के आकार है दोनों कार्यक्रम तर्क और पर्यावरण युक्त)

वैकल्पिक रूप से, अपने कार्यक्रम को संशोधित कुछ विन्यास के माध्यम से विन्यास होने के लिए फ़ाइल जिसमें वह जानकारी होगी जिसमें आप तर्क के माध्यम से गुजरना चाहते हैं।

(यदि आप अपने कर्नेल पुन: संयोजित कर सकते हैं, तो आप ARG_MAX जो आपके कर्नेल फिर कंपाइल से पहले linux-4.*/include/uapi/linux/limits.h में #define -d है 2097152- करने के लिए एक बड़ा अपने उपलब्ध रैम तुलना में काफी छोटा जैसे दो की शक्ति, -to को बढ़ाने के लिए प्रयास कर सकते हैं)

अन्य तरीकों में, वहाँ है कि सीमा को नाकाम करने के कोई रास्ता नहीं है (देखें execve(2) आदमी पेज और और तर्क के आकार पर्यावरण खंड पर अपने सीमा) - एक बार आप अपने ढेर सीमा (RLIMIT_STACK साथ setrlimit(2) का उपयोग कर उठाया है, आम तौर पर पेरेंट खोल में ulimit बिल्टिन के साथ)। आपको अन्यथा इससे निपटने की ज़रूरत है।

+0

'foo' प्रोग्राम को संशोधित नहीं किया जा सकता है। मैं वास्तव में एडब्ल्यूएस एसक्यूएस कमांड लाइन उपकरण को बुला रहा हूं और संदेश को मूल्य के रूप में पास किया जाना है। – swdev

+2

फिर आप अटक गए हैं। –

+0

@swdev: आपको अपने प्रश्न में बाधाओं को निर्दिष्ट करने की आवश्यकता है। एक और तरीका 'xargs' का उपयोग कर वर्गों को तर्क पारित करना होगा। – tuxdna

संबंधित मुद्दे