Torna a cópia de disco / disco mais lenta

23

Existe um método de retardar o processo de cópia no Linux?

Eu tenho um arquivo grande, digamos 10 GB, e gostaria de copiá-lo para outro diretório, mas não quero copiá-lo com velocidade total. Digamos que eu gostaria de copiá-lo com a velocidade de 1mb / s, não mais rápido. Eu gostaria de usar um comando padrão Linux cp .

Isso é possível? (Se sim, como?)

Editar : assim, adicionarei mais contexto ao que estou tentando alcançar.

Eu tenho um problema no sistema ArchLinux ao copiar arquivos grandes via USB (para um pendrive, disco usb, etc). Depois de preencher o cache do buffer usb, meu sistema pára de responder (até o mouse pára; ele se move apenas esporadicamente). A operação de cópia ainda está em andamento, mas leva 100% dos recursos da caixa. Quando a operação de cópia termina, tudo volta ao normal - tudo fica perfeitamente responsivo novamente.

Talvez seja um erro de hardware, não sei, mas sei que tenho duas máquinas com esse problema (ambas estão no ArchLinux, uma é uma caixa de desktop, a segunda é um laptop).

Mais fácil e rápida "solução" para isso (eu concordo que não é a solução 'real', apenas um 'hack' feio) seria impedir que este buffer encher copiando o arquivo com uma velocidade média de gravação do USB dirigir, para mim isso seria suficiente.

    
por antonone 01.03.2014 / 15:37

8 respostas

16

Você pode throttle um cachimbo

tar -cf - . | throttle -M 1 | tar -C /your/usb -xvf -

-b -k -m limites estão em bits e -B -K -M são bytes

    
por 01.03.2014 / 23:07
18

Em vez de cp -a /foo /bar , você também pode usar rsync e limitar a largura de banda conforme necessário.

Do manual do rsync :

--bwlimit=KBPS

limit I/O bandwidth; KBytes per second

Assim, o comando actuall, que também mostra o progresso, ficaria assim:

rsync -av --bwlimit=100 --progress /foo /bar
    
por 02.03.2014 / 01:35
12

Eu diria que você está tentando não atrapalhar outras atividades. Versões recentes do Linux incluem ionice , que permite controlar o agendamento de IO.

Além de permitir várias prioridades, existe uma opção adicional para limitar IO a vezes em que o disco está inativo. O comando man ionice exibirá a documentação.

Tente copiar o arquivo usando um comando como:

ionice -c 3 cp largefile /new/directory

Se os dois diretórios estiverem no mesmo dispositivo, você pode encontrar a vinculação entre o arquivo e o que você deseja. Se você estiver copiando para fins de backup, não use essa opção. ln é extremamente rápido, pois o arquivo em si não é copiado. Experimente:

ln largefile /new/directory

Ou se quiser apenas acessá-lo de um diretório em um dispositivo diferente, tente:

ln -s largefile /new/directory
    
por 01.03.2014 / 17:10
7

Se a solução ionice não for suficiente (por que) e você realmente quiser limitar a E / S a um valor absoluto, existem várias possibilidades:

  1. provavelmente o mais fácil: ssh . Tem um limite interno de largura de banda. Você usaria, e. tar (em vez de cp ) ou scp (se isso for bom o suficiente; não sei como ele lida com links simbólicos e links físicos) ou rsync . Esses comandos podem enviar seus dados por ssh . No caso de tar você escreve para /dev/stdout (ou - ) e canaliza isso para o cliente ssh que executa outro tar no lado "remoto".

  2. elegante, mas não no kernel vanilla (AFAIK): o destino do mapeador de dispositivo ioband . Isso, é claro, funciona apenas se você puder desmontar o volume de origem ou de destino.

  3. alguma diversão escrita por si: grep "^write_bytes: " /proc/$PID/io fornece a quantidade de dados que um processo gravou. Você pode escrever um script que inicie cp no plano de fundo, por exemplo 1/10 segundo, interrompe o plano de fundo cp process ( kill -STOP $PID ), verifica a quantia que foi gravada (e lê? Sobre o mesmo valor nesse caso), calcula por quanto tempo cp deve pausar para leve a taxa de transferência média até o valor pretendido, durma nesse momento, acorde cp ( kill -CONT $PID ) e assim por diante.

por 01.03.2014 / 22:33
5

Seu problema provavelmente não está no seu computador, provavelmente está bem. Mas essa camada de transição flash USB tem um processador próprio que tem que mapear todas as suas gravações para compensar o que poderia ser tanto quanto um chip flash defeituoso de 90%, quem sabe? Você a inunda então você inunda seus buffers, então você inunda o ônibus inteiro, então você está preso, cara - afinal, é aí que estão todas as suas coisas. Pode soar contra-intuitivo, mas o que você realmente precisa é de bloqueio de E / S - você precisa deixar o FTL definir o ritmo e, em seguida, apenas manter-se.

(Em hackers de microcontroladores FTL: link )

Todas as respostas acima devem funcionar, então isso é mais um "eu também!" do que qualquer outra coisa: eu estive totalmente lá, cara. Eu resolvi meus próprios problemas com o - bwlimit rsync (2.5mbs pareciam ser o ponto ideal para uma única execução livre de erros - qualquer coisa a mais e acabaria com erros de proteção contra gravação) . O rsync era especialmente adequado ao meu propósito porque eu estava trabalhando com sistemas de arquivos inteiros - então havia muitos arquivos - e simplesmente executar o rsync pela segunda vez resolveria todos os problemas da primeira execução (o que era necessário quando eu ficava impaciente e tentava para ultrapassar 2.5mbs).

Ainda assim, acho que não é tão prático para um único arquivo. No seu caso, você poderia simplesmente canalizar para dd set para raw-write - você pode manipular qualquer entrada dessa maneira, mas apenas um arquivo de destino de cada vez (embora esse arquivo único possa ser um dispositivo de bloco inteiro, é claro).

## OBTAIN OPTIMAL IO VALUE FOR TARGET HOST DEV ##
## IT'S IMPORTANT THAT YOUR "bs" VALUE IS A MULTIPLE ##
## OF YOUR TARGET DEV'S SECTOR SIZE (USUALLY 512b) ##
% bs=$(blockdev --getoptio /local/target/dev)

## START LISTENING; PIPE OUT ON INPUT ##
% nc -l -p $PORT | lz4 |\ 
## PIPE THROUGH DECOMPRESSOR TO DD ## 
>    dd bs=$bs of=/mnt/local/target.file \
## AND BE SURE DD'S FLAGS DECLARE RAW IO ##
>        conv=fsync oflag=direct,sync,nocache

## OUR RECEIVER'S WAITING; DIAL REMOTE TO BEGIN ##
% ssh [email protected] <<-REMOTECMD
## JUST REVERSED; NO RAW IO FLAGS NEEDED HERE, THOUGH ## 
>    dd if=/remote/source.file bs=$bs |\
>    lz4 -9 | nc local.target.domain $PORT
> REMOTECMD  

Você pode achar o netcat um pouco mais rápido que o ssh para o transporte de dados se você tentar. De qualquer forma, as outras ideias já foram tomadas, então porque não?

[EDIT]: Eu notei as menções de lftp, scp e ssh no outro post e pensei que estávamos falando sobre uma cópia remota. Local é muito mais fácil:

% bs=$(blockdev --getoptio /local/target/dev)
% dd if=/src/fi.le bs=$bs iflag=fullblock of=/tgt/fi.le \
>    conv=fsync oflag=direct,sync,nocache

[EDIT2]: Crédito onde é devido: apenas notei que ptman me bateu nisso por umas cinco horas nos comentários.

Definitivamente, você poderia ajustar o $ bs para performance aqui com um multiplicador - mas alguns sistemas de arquivos podem requerer que ele seja um múltiplo do fsize do alvo, então tenha isso em mente.

    
por 02.03.2014 / 00:49
2

O problema é que a cópia está enchendo sua memória com blocos "em vôo", excluindo dados "úteis". Um bug conhecido (e muito difícil de corrigir) na manipulação de E / S do kernel Linux para dispositivos lentos (USB, neste caso).

Talvez você possa tentar dividir a cópia, por exemplo por um script como o seguinte (esboço de prova de conceito, totalmente não testado!):

while true do
  dd if=infile of=outfile bs=4096 count=... seek=... skip=...
  sleep 5
done

ajustando seek e skip por count a cada rodada. Precisa ajustar count para não encher demais (muito) de memória e 5 para drenar.

    
por 02.03.2014 / 02:55
1

Reduza o limite de páginas sujas. O limite padrão é insano.

Crie /etc/sysctl.d/99-sysctl.conf com:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Em seguida, execute sysctl -p ou reinicialize.

O que está acontecendo é que os dados estão sendo lidos mais rapidamente do que podem ser gravados no disco de destino. Quando o linux copia arquivos, o que ele faz é lê-los na memória RAM e marcar as páginas como sujas para gravar no destino. Páginas sujas não podem ser trocadas. Portanto, se o disco de origem for mais rápido do que o disco de destino e você estiver copiando mais dados do que a RAM livre, a operação de cópia consumirá toda a RAM disponível (ou pelo menos o limite de páginas sujas, que pode ser mais do que RAM disponível) e causar fome, pois as páginas sujas não podem ser trocadas e páginas limpas são usadas e marcadas como sujas.

Note que o seu não irá resolver completamente o problema ... o que o linux realmente precisa é uma maneira de arbitrar a criação de páginas sujas, então uma transferência grande não consome toda RAM disponível / todas as páginas sujas permitidas.

    
por 01.12.2016 / 02:41
0

Este problema não tem nada a ver com erros ou falhas em hardware ou software, é apenas o seu kernel tentando ser legal com você e devolver o seu prompt em segundo plano (ele usa um cache no kernel: mais RAM, mais cache, mas você pode limitá-lo escrevendo em algum lugar em / proc - embora não seja recomendado). Flash drives são muito lentos e enquanto o kernel grava nele, outras operações de IO não podem ser executadas com rapidez suficiente. ionice mencionado várias vezes em outras respostas está ok. Mas você tentou apenas montar a unidade com -o sync para evitar o buffer do sistema operacional? É provavelmente a solução mais simples por aí.

    
por 04.03.2014 / 08:59