CP: argumentos do número máximo de arquivos de origem para o utilitário de cópia

10

Considere que há um número incontável de arquivos em / src /

cp /src/* /dst/

Quantos arquivos cp serão processados com sucesso?

    
por Mike 21.01.2014 / 19:26

2 respostas

16

Isso depende muito do sistema e da versão, do número e tamanho dos argumentos e do número e tamanho dos nomes das variáveis de ambiente.

Tradicionalmente, no Unix, o limite (conforme relatado por getconf ARG_MAX ) era mais ou menos sobre o tamanho cumulativo de:

  • O comprimento das sequências de argumentos (incluindo a finalização ''var=value'' )
  • O comprimento da matriz de ponteiros para essas cadeias, normalmente 8 bytes por argumento em um sistema de 64 bits
  • O comprimento das strings do ambiente (incluindo a finalização cp ), uma string de ambiente sendo por convenção algo como getconf ARG_MAX .
  • O comprimento da matriz de ponteiros para essas cadeias, normalmente 8 bytes por argumento em um sistema de 64 bits

Tendo em conta que zsh também conta como um argumento (é o primeiro argumento).

No Linux, depende da versão. O comportamento lá mudou recentemente, onde não é mais um espaço fixo.

Verificando no Linux 3.11, execve agora reporta um quarto do limite definido no tamanho da pilha, ou 128kiB se for menor que 512kiB).

( %code% sintaxe abaixo):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

Esse limite está no tamanho cumulativo das sequências de argumentos e de ambiente e alguma sobrecarga (suspeito que devido à consideração de alinhamento nos limites da página). O tamanho dos ponteiros não é levado em conta.

Procurando pelo limite, recebo:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

O tamanho máximo cumulativo antes de quebrar nesse caso é:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

Agora, isso não significa que você possa passar 1 milhão de argumentos vazios. Em um sistema de 64 bits, 1 milhão de argumentos vazios formam uma lista de 8MB, que estaria acima do tamanho de pilha de 4MiB.

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(você notará que não é um erro E2BIG. Não sei em que ponto o processo é eliminado, embora esteja dentro da chamada do sistema %code% ou posterior).

Observe também (ainda no Linux 3.11) que o tamanho máximo de um único argumento ou string de ambiente é 128kiB, independentemente do tamanho da pilha.

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK
    
por 22.01.2014 / 00:16
13

Isso dependerá do valor de ARG_MAX que pode mudar entre os sistemas. Para descobrir o valor do seu sistema executado (mostrando o resultado no meu como exemplo):

$ getconf ARG_MAX
2097152

Isso não tem nada a ver com cp ou seu shell, é um limite imposto pelo kernel, ele não executará comandos ( exec() ) se seus argumentos forem maiores que ARG_MAX . Então, se o tamanho da lista de argumentos que você deu para cp for maior que ARG_MAX, o comando cp não será executado.

Para responder à sua questão principal, cp não processará nenhum arquivo, pois ele nunca será executado com tantos argumentos. Também devo mencionar que isso não depende do número de argumentos, mas do tamanho deles. Você poderia ter o mesmo problema com poucos, mas muito longos nomes de arquivos.

A maneira de contornar esses erros é executar seu comando em um loop:

for file in /src/*; do cp "$file" /dst/; done
    
por 21.01.2014 / 19:44

Tags