Enviando a saída de 'dd' para awk / sed / grep

6

Estou tentando aproximar a velocidade de gravação do computador usando o dd:

dd if=/dev/urandom of=/dev/null bs=1K count=10000

que fornece o seguinte resultado

10000+0 records in
10000+0 records out
10240000 bytes (10 MB) copied, 0.746313 s, 13.7 MB/s

Como posso obter os '13.7 MB / s 'em uma variável bash? Eu tentei piping a saída de dd para progs como awk, sed e grep sem sucesso.

Por fim, estou chamando isso via os.system(...) de um script python. Se alguém souber de uma maneira mais direta de obter um resultado semelhante dentro do python, eu também estaria interessado nisso. Estou tentando prever quanto tempo uma cópia de arquivo levará, com base no tamanho do arquivo.

Qualquer ajuda seria muito apreciada.

    
por Gilles 24.07.2012 / 23:48

4 respostas

8

O problema é que sua saída designada do dd vai para STDERR e não STDOUT , então você também tem que redirecionar STDERR e não apenas STDOUT .

Para o bash e o zsh, você pode usar |& em vez de | , o que também redirecionará STDERR a STDIN do segundo comando, por exemplo:

dd if=/dev/urandom of=/dev/null bs=1K count=10000 |& awk '/copied/ {print $8 " "  $9}'

A abordagem mais geral é redirecionar STDERR explicitamente com 2>&1 , por exemplo:

dd if=/dev/urandom of=/dev/null bs=1K count=10000 2>&1 | awk '/copied/ {print $8 " "  $9}'

Para a parte em python, consulte o módulo do subprocesso e Popen em particular.

    
por 25.07.2012 / 00:10
2
var=$(dd if=/dev/urandom of=/dev/null bs=1K count=10000 2>&1)
var=$(echo ${var##*,})
    
por 25.07.2012 / 00:13
1

Como a expansão de parâmetros do Bash evita o uso de comandos externos, é uma solução boa e elegante que 1_CR propôs .

No entanto, sua proposta retorna o valor errado (isto é, apenas o valor por trás da vírgula):

$ var=$(dd if=/dev/urandom of=/dev/null bs=1K count=10000 2>&1)
$ var=$(echo ${var##*,})
$ echo $var
8 MB/s # the wrong value

Enquanto a seguinte resposta correta daria:

$ var=$(dd if=/dev/urandom of=/dev/null bs=1K count=10000 2>&1)
$ var=$(echo ${var##*s,})
$ echo $var
11,8 MB/s # the right value
    
por 03.02.2015 / 16:01
0

Outra variação no tema, obtendo todos os campos pertinentes, evitando chamadas externas para awk ou sed (usa read, que no bash é um built-in)

IFS=' +' read in_full in_part _x _x \
out_full out_part _x _x \
bytes _x _x _x _x seconds _x speed speed_units < <(
  echo $(dd if=/dev/zero of=/dev/null bs=1024 count=7 2>&1) 
)

echo -e "$bytes bytes were read in $seconds seconds, speed was $speed $speed_units.\n$in_full full blocks, and $in_part partial blocks were read in.\n$out_full full blocks, and $out_part partial blocks were written out."

A mesma coisa em uma linha (sem quebras de linha)

IFS=' +' read in_full in_part _x _x out_full out_part _x _x bytes _x _x _x _x seconds _x speed speed_units < <( echo $(dd if=/dev/zero of=/dev/null bs=1024 count=7 2>&1) )
echo -e "$bytes bytes were read in $seconds seconds, speed was $speed $speed_units.\n$in_full full blocks, and $in_part partial blocks were read in.\n$out_full full blocks, and $out_part partial blocks were written out."
    
por 10.06.2016 / 14:36