Estou tentando entender a página de manual do dd
programa, que menciona:
Enviar um sinal USR1 para um processo 'dd' em execução faz com que ele imprima estatísticas de E/S com erro padrão e depois retome a cópia.
$ dd if=/dev/zero of=/dev/null& pid=$! $ kill -USR1 $pid; sleep 1; kill $pid
O que pid=$!
significa?
Esta é uma atribuição de uma variável que obtém o pid de dd
? E eventualmente é usado na $pid
variável?
Além disso, por que eles usam sleep
e kill
?
É esse o jeito de usar -USR1
?
Responder1
dd if=/dev/zero of=/dev/null&
O final &
significa executar o comando prefixo em segundo plano. (Isenção de responsabilidade: esta é uma declaração simplificada demais)
Referir-seesse:
$! é o PID do comando em segundo plano mais recente.
Então pid=$!
atribua oPID de fundo mais recentepara a variável pid, que é dd
PID.
Também por que eles usam dormir e matar?
Você precisakill $pid
(se o parâmetro não for especificado, o sinal padrão para kill é TERM, que é o encerramento do processo)para encerrar o dd
processo após a conclusão do teste, caso contrário, dd
o processo poderá permanecer em segundo plano e esgotar os recursos da CPU. Verifique o Monitor do Sistema da sua plataforma para ver.
Enquanto Kill -USR1 $pid
imprime estatísticas de E/S, isso não encerra o processo.
Sem dormir 1 segundo, seu dd
processo pode ser encerrado pela última instrução de comando kill $pid
** antes de ter a chance de gravar a saída de estatísticas em seu terminal. Os processos são síncronos, masoperação trap+write( kill -USR1 $pid
) pode ser mais lento queencerrar operação( kill $pid
). Portanto sleep 1
, é necessário atrasar a inicialização kill $pid
para garantir a impressão da saída de estatísticas.
Esta é a maneira de usar -USR1?
Apenas man dd
:
Enviar um sinal USR1 para um processo 'dd' em execução faz com que ele imprima estatísticas de E/S com erro padrão e depois retome a cópia.
E man 7 signal
:
SIGUSR1 30,10,16 Term User-defined signal 1 SIGUSR2 31,12,17 Term User-defined signal 2
Combine as duas declarações, você deve entender que USR1 éSinal definido pelo usuárioque é definido por dd
para fornecer uma maneira para o usuário interrompê-lo eimprimir estatísticas de E/Sno vôo. É um manipulador específico do programa, isso não significa que você pode kill -USR1 other_program_pid
e espera a saída de estatísticas.
Além disso, você pode se interessar poristo: Por que SIGUSR1 faz com que o processo seja encerrado?.
Responder2
Esta é apenas uma demonstração para ilustrar o uso do USR1
sinal com dd
.
dd if=/dev/zero of=/dev/null &
começa dd
em segundo plano, copiando dados de /dev/zero
(que produz zeros sempre que um programa os lê) para /dev/null
(que descarta qualquer coisa escrita nele). Isso fornece uma instância inofensiva dd
que pode ser usada para experiências - ela não consome nenhum armazenamento e continuará funcionando pelo tempo que desejarmos, o que dá ao usuário tempo para enviar sinais a ela.
pid=$!
armazena o identificador do processo do último comando em segundo plano ( $!
) na variável pid
.
kill -USR1 $pid
envia o USR1
sinal para o processo cujo identificador é o valor armazenado na pid
variável, dd
neste caso o background. Ao dd
receber este sinal, ele imprime seu progresso atual (a quantidade de dados lidos e gravados) e continua copiando.
sleep 1
espera um segundo.
kill $pid
envia o TERM
sinal para dd
, o que faz com dd
que saia. (Não faz sentido deixar o plano de fundo dd
rodando aqui.)
Seria mais instrutivo executar isto em vez da segunda linha acima:
kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid
Isto produziria o progresso duas vezes, com um segundo entre, para mostrar dd
o progresso de; então mate dd
sem esperar.
Para uso real, você especificaria entradas e saídas apropriadas para o dd
comando original, e provavelmente algumas outras opções também, e não executaria a última kill
- esperaria dd
que ele terminasse por conta própria.
Para responder à sua pergunta final, é assim que você envia USR1
sinais de um shell (ou qualquer outro sinal): você usakill
com o sinal que você deseja enviar e os identificadores de processo (ou identificadores de trabalho) dos processos para os quais deseja enviar o sinal. Outros comandos (não POSIX) que você pode usar sãopkill
ekillall
, quando você deseja localizar processos por nome.
Responder3
Para a maioria ou todos os shells, $!
é o ID do processo (também chamado de PID) do último processo que o shell bifurcou. O dd
comando foi bifurcado com &
, de modo que pid=$!
logo após a bifurcação dd
atribui dd
o ID do processo à variável shell pid
.
Um ID de processo é um número usado pelo Linux ou Unix para se referir a um espaço de endereço com algum código em execução nele.
O kill
programa tem um nome pouco intuitivo, pois sua finalidade é enviar sinais (mensagens pequenas e assíncronas) aos processos. Existem apenas alguns sinais, talvez 128 no total, eles têm números e nomes. O sinal de “matar” é o número 9, por exemplo. USR1 é definido como o número 10. Portanto, kill -USR1 $pid
envia o sinal 10 para o processo numerado $pid
. dd
às vezes leva muito tempo para ser executado, então esse é quase certamente o ID do processo do dd
comando que foi bifurcado anteriormente e executado em segundo plano. O kill $pid
comando envia um sinal TERM para esse mesmo ID de processo. TERM significa "rescindir". Programas bem escritos geralmente capturam o TERM, limpam os recursos alocados e depois saem.
Não tenho muita certeza de por que você executaria dd
em segundo plano, enviaria um sinal USR1 para ele, esperaria 1 segundo e, em seguida, faria com dd
que todos os recursos fossem desalocados e saísse. Todo o fragmento de código parece assumir que dd
é executado por um longo tempo, o que pode não ser verdade. Acho que existem condições de corrida neste código e, seja qual for a semântica desejada, você pode não obtê-las.
Responder4
Se você espera que dd
o comando seja executado em primeiro plano e exiba o status do progresso atual. tente executar o comando com status=progress
flag:
sudo dd if=/dev/sda of=/dev/sdb status=progress
Isso exibirá dinamicamente o progresso.
Essa é uma extensão da implementação GNU dd
(adicionada na versão 8.24 lançada em 2015), também disponível na dd
implementação no FreeBSD desde 12.0 (2018), mas geralmente não em outras implementações, inclusive em outros BSDs.