Você usou o mesmo shell nos dois experimentos? Talvez /bin/bashvs. /bin/sh(que talvez seja um link para o dash)?
maxschlepzig
Sim, fiz o experimento com 10000 arquivos com nome de arquivo bastante longos. "ls *" falhou e "for f in *" foi bem-sucedido.
lamwaiman1988
Respostas:
13
O erro "argumento muito longo" é E2BIGgerado pela execvechamada do sistema se o tamanho total dos argumentos (mais o ambiente, em alguns sistemas) for muito grande. A execvechamada é aquela que inicia processos externos, carregando especificamente um arquivo executável diferente (há uma chamada diferente fork, para executar um processo separado cujo código ainda é do mesmo arquivo executável). O forloop é uma construção de shell interna, portanto, não envolve chamadas execve. O comando ls *.*gera o erro não quando o glob é expandido, mas quando lsé chamado.
execvefalha com o erro E2BIGquando o tamanho total dos argumentos para o comando é maior que o ARG_MAXlimite . Você pode ver o valor desse limite em seu sistema com o comando getconf ARG_MAX. (É possível que você ultrapasse esse limite se tiver memória suficiente; mantendo as ARG_MAXgarantias de que execvefuncionará enquanto não ocorrer nenhum erro não relacionado.)
@ gunbuster363 O execvelimite é imposto pelo kernel, coloca limites porque os argumentos precisam ser copiados via memória do kernel em um ponto e os processos do usuário não podem solicitar uma quantidade arbitrária de memória shell. Dentro do shell, não há razão para ter qualquer limite, tudo o que se encaixa na memória virtual é bom.
Gilles 'SO- stop be evil'
5
Suponho que no primeiro exemplo lsseja executado bashatravés de uma chamada de sistema fork/ execpair, no segundo, todo o trabalho seja interno bash.
A execchamada tem limites, o trabalho interno em bashvez disso não tem (ou melhor, possui limites diferentes que não têm nada a ver com exec, talvez a quantidade de memória disponível).
Definitivamente, há um limite para a expansão do shell. Está muito relacionado à quantidade de RAM que você tem disponível. Tente isso; meu sistema RAM 4GB sopra uma junta em cerca de 15,2 milhões de args de 8 bytes:for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
Peter.O
4
@ Fred Eu realmente não acho necessário mencionar a RAM como limite.
Šimon Tóth
2
Pode não ser necessário, mas essa é a natureza dos comentários. Alguém pode achar interessante, ou mesmo de valor.
precisa saber é o seguinte
@ Fred: na verdade, sim, se expandir argumentos muito grandes fosse um problema comum, seria possível implementá-lo sem manter tudo na memória.
/bin/bash
vs./bin/sh
(que talvez seja um link para o dash)?Respostas:
O erro "argumento muito longo" é
E2BIG
gerado pelaexecve
chamada do sistema se o tamanho total dos argumentos (mais o ambiente, em alguns sistemas) for muito grande. Aexecve
chamada é aquela que inicia processos externos, carregando especificamente um arquivo executável diferente (há uma chamada diferentefork
, para executar um processo separado cujo código ainda é do mesmo arquivo executável). Ofor
loop é uma construção de shell interna, portanto, não envolve chamadasexecve
. O comandols *.*
gera o erro não quando o glob é expandido, mas quandols
é chamado.execve
falha com o erroE2BIG
quando o tamanho total dos argumentos para o comando é maior que oARG_MAX
limite . Você pode ver o valor desse limite em seu sistema com o comandogetconf ARG_MAX
. (É possível que você ultrapasse esse limite se tiver memória suficiente; mantendo asARG_MAX
garantias de queexecve
funcionará enquanto não ocorrer nenhum erro não relacionado.)fonte
execve
limite é imposto pelo kernel, coloca limites porque os argumentos precisam ser copiados via memória do kernel em um ponto e os processos do usuário não podem solicitar uma quantidade arbitrária de memória shell. Dentro do shell, não há razão para ter qualquer limite, tudo o que se encaixa na memória virtual é bom.Suponho que no primeiro exemplo
ls
seja executadobash
através de uma chamada de sistemafork
/exec
pair, no segundo, todo o trabalho seja internobash
.A
exec
chamada tem limites, o trabalho interno embash
vez disso não tem (ou melhor, possui limites diferentes que não têm nada a ver comexec
, talvez a quantidade de memória disponível).fonte
exec
em/usr/include/linux/limits.h
geral, definido comoARG_MAX
.Porque, no caso
ls
, é um argumento, e o número de argumentos é limitado.No caso do
for
ciclo, é apenas uma lista de itens. Não há limites (até onde eu saiba) para isso.fonte
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done