프로그램의 명령줄에서 신호를 사용/보내는 방법(예: dd)

프로그램의 명령줄에서 신호를 사용/보내는 방법(예: dd)

나는 dd다음과 같은 프로그램 맨페이지를 이해하려고 노력하고 있습니다.

실행 중인 "dd" 프로세스에 USR1 신호를 보내 I/O 통계를 표준 오류로 인쇄한 다음 복제를 재개합니다.

         $ dd if=/dev/zero of=/dev/null& pid=$!
         $ kill -USR1 $pid; sleep 1; kill $pid

무슨 뜻이에요 pid=$!?

이것은 변수에 대한 할당입니까? pid를 얻습니까 dd? 궁극적으로 $pid변수에 사용됩니까?

또한 왜 사용 sleep합니까 kill?

사용방법은 이렇나요 -USR1?

답변1

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

후행은 &백그라운드에서 prefix 명령을 실행하는 것을 의미합니다. (면책조항: 이는 지나치게 단순화된 진술입니다)

인용하다이것:

$! 가장 최근의 백그라운드 명령의 PID입니다.

그래서 pid=$!할당가장 최근의 배경 PIDPID 인 변수 pid에 dd.

그리고 왜 그들은 잠을 자고 죽임을 사용합니까?

당신은해야합니다kill $pid (매개변수가 지정되지 않은 경우 kill의 기본 신호는 TERM이며 이는 프로세스가 종료됨을 의미합니다.)dd테스트를 완료한 후 프로세스를 종료하십시오. 그렇지 않으면 dd프로세스가 백그라운드에 남아 CPU 리소스를 소모할 수 있습니다. 플랫폼의 시스템 모니터를 확인하여 확인하세요.

I/O 통계가 인쇄 되지만 Kill -USR1 $pid프로세스가 종료되지는 않습니다.

dd1초 동안 대기하지 않으면 프로세스가 터미널에 통계 출력을 쓰기 전에 마지막 명령문에 의해 프로세스가 종료될 수 있습니다 . kill $pid이러한 프로세스는 동기화되지만트랩+쓰기 작업( kill -USR1 $pid)는 다음보다 느릴 수 있습니다.작업 종료( kill $pid). 따라서 두 번째는 통계 출력 인쇄가 완료되었는지 확인하기 위해 sleep 1시작을 지연하는 것입니다 .kill $pid

이것이 -USR1이 사용되는 방식입니까?

오직 man dd:

실행 중인 "dd" 프로세스에 USR1 신호를 보내 I/O 통계를 표준 오류로 인쇄한 다음 복제를 재개합니다.

그리고 man 7 signal:

   SIGUSR1   30,10,16    Term    User-defined signal 1
   SIGUSR2   31,12,17    Term    User-defined signal 2

이 두 진술을 결합하면 USR1이 다음과 같다는 것을 이해해야 합니다.사용자 정의 신호그 정의는 dd사용자에게 이를 중단할 수 있는 방법을 제공하는 것입니다.I/O 통계 인쇄비행 중. 이는 프로그램별 처리기이며 kill -USR1 other_program_pid통계적 출력을 기대할 수 있다는 의미는 아닙니다.

당신은 또한에 관심이있을 수 있습니다이: SIGUSR1로 인해 프로세스가 종료되는 이유는 무엇입니까?.

답변2

USR1이것은 신호의 사용을 설명하기 위한 데모일 뿐입니다 dd.

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

dd백그라운드에서 시작하여 데이터는 (프로그램이 읽을 때마다 0을 생성함)에서 (기록된 내용을 모두 삭제) /dev/zero로 복사 됩니다. /dev/null이는 dd실험에 사용할 수 있는 무해한 인스턴스를 제공합니다. 이는 저장 공간을 차지하지 않고 원하는 만큼 계속 실행될 수 있으므로 사용자가 신호를 보낼 시간을 제공합니다.

pid=$!

마지막 백그라운드 명령의 프로세스 식별자를 $!변수에 저장합니다 pid.

kill -USR1 $pid

식별자가 변수(이 경우 배경) USR1에 저장된 값인 프로세스에 신호를 보냅니다 . 이 신호를 받으면 현재 진행 상황(읽고 쓴 데이터의 양)을 인쇄하고 계속 복사합니다.piddddd

sleep 1

잠깐만.

kill $pid

TERM에 신호를 보내 종료 dd되도록 합니다 dd. (백그라운드에서 실행하는 것은 여기서 의미가 없습니다 dd.)

위의 두 번째 줄 대신 이것을 실행하는 것이 더 유익할 것입니다.

kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid

dd진행 상황을 표시하기 위해 1초 간격으로 진행 상황을 두 번 출력한 다음 dd기다리지 않고 종료합니다.

실제 사용을 위해 dd원래 명령에 대한 적절한 입력 및 출력(몇 가지 추가 옵션 포함)을 지정하고 마지막 명령을 실행하지 않고 자체적으로 완료될 때 kill까지 기다립니다 .dd

USR1마지막 질문에 답하기 위해 쉘(또는 다른 신호)에서 신호를 보내는 방법은 다음과 같습니다.kill전송될 신호와 신호가 전송되는 프로세스의 프로세스 식별자(또는 작업 식별자)를 포함합니다. 사용할 수 있는 기타(POSIX가 아닌) 명령은 다음과 같습니다.pkill그리고killall, 이름으로 프로세스를 찾고 싶을 때.

답변3

대부분 또는 모든 셸의 경우, $!셸에서 분기된 마지막 프로세스의 프로세스 ID(PID라고도 함)입니다. 이 dd명령은 포크를 사용하여 포크의 오른쪽이 프로세스 ID를 쉘 변수에 할당하도록 &합니다 .pid=$!ddddpid

프로세스 ID는 Linux 또는 Unix에서 일부 코드가 실행되는 주소 공간을 참조하는 데 사용되는 숫자입니다.

프로그램 kill이름은 그 목적이 프로세스에 신호(작은 비동기 메시지)를 보내는 것이기 때문에 직관적이지 않습니다. 약 128개의 신호만 있으며 모두 번호와 이름이 지정되어 있습니다. 예를 들어, "kill" 신호는 숫자 9입니다. USR1은 숫자 10으로 정의됩니다. 따라서 kill -USR1 $pid신호 10이 프로세스 번호 로 전송됩니다 $pid. dd때로는 실행하는 데 오랜 시간이 걸리므로 이는 dd이전에 분기되어 백그라운드에서 실행된 명령의 프로세스 ID인 것이 거의 확실합니다. 이 kill $pid명령은 동일한 프로세스 ID에 TERM 신호를 보냅니다. TERM은 "종료"를 의미합니다. 잘 작성된 프로그램은 일반적으로 TERM을 포착하고 할당된 리소스를 정리한 다음 종료됩니다.

dd왜 백그라운드에서 실행하고 USR1 신호를 보내고 1초 동안 기다린 다음 dd모든 리소스를 해제하고 종료하는지 잘 모르겠습니다 . 전체 코드 조각에서는 dd실행하는 데 오랜 시간이 걸린다고 가정하는 것 같지만 사실이 아닐 수도 있습니다. 내 생각에 이 코드에는 경쟁 조건이 있으며 원하는 의미가 무엇이든 실제로 얻지 못할 수도 있습니다.

답변4

dd명령을 포그라운드에서 실행하고 현재 진행 상태를 표시하려는 경우 . status=progress플래그를 사용하여 명령을 실행 해 보세요 .

sudo dd if=/dev/sda of=/dev/sdb status=progress

그러면 진행 상황이 동적으로 표시됩니다.

이는 12.0(2018) 이후 FreeBSD에서의 구현에도 사용할 수 있는 GNU 구현 dd(2015년에 출시된 버전 8.24에 추가됨) 에 대한 확장이지만 일반적으로 다른 BSD에서의 다른 구현은 제외됩니다.dd

관련 정보