Como usar/enviar sinais na linha de comando, para qualquer programa (por exemplo, dd)

Como usar/enviar sinais na linha de comando, para qualquer programa (por exemplo, dd)

Estou tentando entender a página de manual do ddprograma, 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 $pidvariável?

Além disso, por que eles usam sleepe 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 é ddPID.

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 ddprocesso após a conclusão do teste, caso contrário, ddo 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 $pidimprime estatísticas de E/S, isso não encerra o processo.

Sem dormir 1 segundo, seu ddprocesso 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 $pidpara 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 ddpara 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_pide 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 USR1sinal com dd.

dd if=/dev/zero of=/dev/null &

começa ddem 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 ddque 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 USR1sinal para o processo cujo identificador é o valor armazenado na pidvariável, ddneste caso o background. Ao ddreceber 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 TERMsinal para dd, o que faz com ddque saia. (Não faz sentido deixar o plano de fundo ddrodando 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 ddo progresso de; então mate ddsem esperar.

Para uso real, você especificaria entradas e saídas apropriadas para o ddcomando original, e provavelmente algumas outras opções também, e não executaria a última kill- esperaria ddque ele terminasse por conta própria.

Para responder à sua pergunta final, é assim que você envia USR1sinais de um shell (ou qualquer outro sinal): você usakillcom 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ãopkillekillall, 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 ddcomando foi bifurcado com &, de modo que pid=$!logo após a bifurcação ddatribui ddo 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 killprograma 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 $pidenvia 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 ddcomando que foi bifurcado anteriormente e executado em segundo plano. O kill $pidcomando 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 ddem segundo plano, enviaria um sinal USR1 para ele, esperaria 1 segundo e, em seguida, faria com ddque 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 ddo comando seja executado em primeiro plano e exiba o status do progresso atual. tente executar o comando com status=progressflag:

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 ddimplementação no FreeBSD desde 12.0 (2018), mas geralmente não em outras implementações, inclusive em outros BSDs.

informação relacionada