Riga di comando Bash e limite di input


91

C'è una sorta di limite di caratteri imposto in bash (o altre shell) per quanto tempo può essere un input? In caso affermativo, qual è il limite di caratteri?

Vale a dire, è possibile scrivere un comando in bash che è troppo lungo per essere eseguito dalla riga di comando? Se non c'è un limite richiesto, c'è un limite suggerito?


2
Il limite di input è molto diverso dal limite di argomenti a livello di sistema operativo (si noti che alcune cose diverse dagli argomenti, come le variabili di ambiente, si applicano anche a quello). Il comando generato passato al sistema operativo può contenere più o meno caratteri del comando shell che lo ha generato.
Charles Duffy

Risposte:


129

Il limite per la lunghezza di una riga di comando non è imposto dalla shell, ma dal sistema operativo. Questo limite è generalmente compreso tra centinaia di kilobyte. POSIX denota questo limite ARG_MAXe sui sistemi conformi a POSIX è possibile interrogarlo

$ getconf ARG_MAX    # Get argument limit in bytes

Ad esempio, su Cygwin questo è 32000, e sui diversi BSD e sistemi Linux che uso è da 131072 a 2621440.

Se è necessario elaborare un elenco di file che superano questo limite, è possibile esaminare l' xargsutilità, che richiama ripetutamente un programma con un sottoinsieme di argomenti non superiore ARG_MAX.

Per rispondere alla tua domanda specifica, sì, è possibile tentare di eseguire un comando con un elenco di argomenti troppo lungo. La shell restituirà un messaggio di errore con "elenco di argomenti troppo lungo".

Si noti che l' input in un programma (come letto su stdin o qualsiasi altro descrittore di file) non è limitato (solo dalle risorse del programma disponibili). Quindi, se il tuo script di shell legge una stringa in una variabile, non sei limitato da ARG_MAX. La restrizione inoltre non si applica ai comandi incorporati della shell.


Bella risposta, ma vorrei un chiarimento. Se ottenessi un costrutto cmd <<< "$LONG_VAR"e il valore LONG_VAR superasse il limite, il mio comando salterebbe?
Krzysztof Jabłoński

1
@ KrzysztofJabłoński Improbabile, perché il contenuto di LONG_VARviene passato allo stdin - e questo viene fatto interamente nella shell; non è espanso come argomento a cmd, quindi il limite ARG_MAX per fork () / exec () non entra in gioco. È facile provare tu stesso: crea una variabile con contenuti che eccedono ARG_MAX ed esegui il tuo comando.
Jens

2
Ecco il chiarimento, per la cronaca: un file m4a 8 megabyte, l'ho fatto: blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null. Non notare alcun errore.
Mike S

4
Piccolo avvertimento. Contano anche le variabili d'ambiente. sysconf manpage > È difficile usare ARG_MAX perché non è specificato quanto> dello spazio degli argomenti per exec (3) viene consumato dalle variabili di ambiente> dell'utente.
Gerrit

3
@ user188737 Mi sento come se fosse un avvertimento piuttosto grande in BUGS . Per esempio xargssu MacOS 10.12.6 limiti quanto cerca di mettere in uno exec()a ARG_MAX - 4096. Quindi l'uso degli script xargspotrebbe funzionare, fino a quando un giorno qualcuno mette troppa roba nell'ambiente. Incontralo ora (aggiralo con :) xargs -s ???.
neuralmer

45

Ok, abitanti. Quindi ho accettato i limiti di lunghezza della riga di comando come gospel per un bel po 'di tempo. Allora, cosa fare con le proprie supposizioni? Naturalmente, controllali.

Ho una macchina Fedora 22 a mia disposizione (che significa: Linux con bash4). Ho creato una directory con 500.000 inode (file) ciascuno di 18 caratteri. La lunghezza della riga di comando è 9.500.000 caratteri. Creato così:

seq 1 500000 | while read digit; do
    touch $(printf "abigfilename%06d\n" $digit);
done

E notiamo:

$ getconf ARG_MAX
2097152

Nota comunque che posso farlo:

$ echo * > /dev/null

Ma questo fallisce:

$ /bin/echo * > /dev/null
bash: /bin/echo: Argument list too long

Posso eseguire un ciclo for:

$ for f in *; do :; done

che è un altro builtin della shell.

Lettura attenta della documentazione per gliARG_MAX stati, lunghezza massima degli argomenti per le funzioni exec . Ciò significa: senza chiamare exec, non ci sono ARG_MAXlimitazioni. Quindi spiegherebbe perché i builtin della shell non sono limitati da ARG_MAX.

E in effetti, posso la lsmia directory se il mio elenco di argomenti è lungo 109948 file o circa 2.089.000 caratteri (dare o prendere). Una volta aggiunto un altro file di nome file di 18 caratteri, tuttavia, viene visualizzato un errore di elenco di argomenti troppo lungo . Quindi ARG_MAXfunziona come pubblicizzato: l'exec sta fallendo con più di ARG_MAXcaratteri nell'elenco degli argomenti, inclusi, va notato, i dati dell'ambiente.


Hmm. Non avevo letto la risposta esistente per implicare che i incorporati fossero soggetti al vincolo in questione, ma posso certamente vedere come qualcuno potrebbe.
Charles Duffy

6
Sì, penso che sia difficile ricordare, specialmente per gli afficianados della riga di comando più recenti, che la situazione di chiamare un builtin bash contro fork / eseguire un comando è diversa in modi non ovvi. Volevo che fosse chiaro. Una domanda che ricevo invariabilmente in un colloquio di lavoro (come amministratore di sistema Linux) è: "Quindi ho un mucchio di file in una directory. Come faccio a farli scorrere tutti in loop ..." L'interrogante sta invariabilmente guidando verso la linea limite di lunghezza e vuole una soluzione find / while o xargs. In futuro dirò, "ah diavolo, usa solo un ciclo for. Può gestirlo!" :-)
Mike S

@MikeS Anche se potresti fare un ciclo for, se puoi usare una combo find-xargs biforcerai molto meno e sarai più veloce. ;-)
Lester Cheung

4
@LesterCheung for f in *; do echo $f; donenon esegue il fork (tutti i builtin). Quindi non so se una combo find-xargs sarà più veloce; non è stato testato. In effetti, non so quale sia la serie di problemi dell'OP. Forse find /path/to/directorynon gli sarà utile perché restituirà il percorso del file. Forse gli piace la semplicità di un for f in *loop. Indipendentemente da ciò, la conversazione riguarda il limite dell'ingresso di linea e non l'efficienza. Quindi rimaniamo in argomento, che riguarda la lunghezza della riga di comando.
Mike S

FWIW, il problema, se ricordo bene, stava solo cercando di scrivere una shell in C e determinare quanto tempo avrei dovuto consentire agli input.
Derek Halden

-3

C'è un limite di buffer di qualcosa come 1024. La lettura si bloccherà semplicemente a metà incolla o input. Per risolvere questo problema, usa l'opzione -e.

http://linuxcommand.org/lc3_man_pages/readh.html

-e usa Readline per ottenere la riga in una shell interattiva

Cambia la tua lettura in read -e e il fastidioso blocco dell'input di linea scompare.


1
Non si tratta di read: "Vale a dire, è possibile scrivere un comando in bash che è troppo lungo per essere eseguito dalla riga di comando?"
Chai T. Rex

@ ChaiT.Rex hai ragione, ma ecco il punto: prova a eseguire Bash in modo interattivo senza Readline, cioè bash --noediting, e al nuovo prompt prova a eseguire il comando echo somereallylongword, dove somereallylongword è più lungo di 4090 caratteri. Provato su Ubuntu 18.04, la parola è stata troncata, quindi ovviamente ha qualcosa a che fare con Readline non abilitato.
Amir

@Amir Interessante! Hai ragione! Ho provato a modificare la risposta, ma poi mi sono reso conto che l'opzione -e non si applica a bash in questo contesto (in bash, esce immediatamente dalla shell in caso di errore). E non sono sicuro del motivo per cui Paul ha deciso di leggere. Ad ogni modo, c'è un limite di buffer compreso tra 4-5000 caratteri quando bash viene avviato con --noreadline. Questo è un effetto collaterale che non sapevo o mi aspettavo.
Mike S
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.