Я пытаюсь понять страницу руководства dd
программы, в которой упоминается:
Отправка сигнала USR1 запущенному процессу «dd» заставляет его выводить статистику ввода-вывода в стандартный поток ошибок, а затем возобновлять копирование.
$ 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&
Конечный символ &
означает запуск команды префикса в фоновом режиме. (Отказ от ответственности: это слишком упрощенное утверждение)
Ссылаться наэтот:
$! — это PID последней фоновой команды.
Итак, pid=$!
назначьтеСамый последний фоновый PIDк переменной pid, которая является dd
PID.
И почему они используют сон и убийство?
Тебе нужноkill $pid
(если параметр не указан, сигналом по умолчанию для kill является TERM, что означает завершение процесса)чтобы завершить dd
процесс после завершения тестирования, в противном случае dd
процесс может просто остаться в фоновом режиме и истощить ресурсы вашего процессора. Проверьте ваш системный монитор вашей платформы, чтобы увидеть.
При Kill -USR1 $pid
печати статистики ввода-вывода процесс не завершается.
Без сна в 1 секунду ваш dd
процесс может быть завершен последним оператором команды kill $pid
** до того, как появится возможность записать вывод статистики на ваш терминал. Процессы синхронны, нооперация ловушка+запись( kill -USR1 $pid
) может быть медленнее, чемзавершить операцию( kill $pid
). Поэтому sleep 1
во-вторых, отложите запуск, kill $pid
чтобы гарантировать, что вывод статистики будет выполнен.
Вот как использовать -USR1?
Только man dd
:
Отправка сигнала USR1 запущенному процессу «dd» заставляет его выводить статистику ввода-вывода в стандартный поток ошибок, а затем возобновлять копирование.
И man 7 signal
:
SIGUSR1 30,10,16 Term User-defined signal 1 SIGUSR2 31,12,17 Term User-defined signal 2
Объедините оба утверждения, и вы поймете, что USR1 — этоСигнал, определяемый пользователемкоторый определяется как dd
предоставление пользователю возможности прервать его ираспечатать статистику ввода-выводана лету. Это обработчик, специфичный для программы, это не значит, что вы можете kill -USR1 other_program_pid
ожидать вывода статистики.
Также вас может заинтересовать информация оэто: Почему SIGUSR1 приводит к завершению процесса?.
решение2
Это всего лишь демонстрация, иллюстрирующая использование USR1
сигнала dd
.
dd if=/dev/zero of=/dev/null &
запускается dd
в фоновом режиме, копируя данные из /dev/zero
(который выдает нули всякий раз, когда программа читает из него) в /dev/null
(который отбрасывает все, что в него записано). Это обеспечивает безвредный экземпляр, с dd
которым можно экспериментировать — он не использует память и будет работать столько, сколько мы захотим, что дает пользователю время отправлять ему сигналы.
pid=$!
сохраняет идентификатор процесса последней фоновой команды ( $!
) в переменной pid
.
kill -USR1 $pid
посылает USR1
сигнал процессу, идентификатор которого — значение, сохраненное в переменной, в данном случае pid
фон . Получив этот сигнал, он выводит свой текущий прогресс (объем прочитанных и записанных данных) и продолжает копирование.dd
dd
sleep 1
ждет одну секунду.
kill $pid
посылает TERM
сигнал dd
, что приводит dd
к выходу. (Нет смысла оставлять фоновый процесс dd
запущенным здесь.)
Было бы более поучительно запустить это вместо второй строки выше:
kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid
Это выведет прогресс дважды с интервалом в одну секунду, чтобы показать dd
прогресс; затем завершит работу dd
без ожидания.
Для фактического использования вам нужно будет указать соответствующие входные и выходные данные для исходной dd
команды, а также, возможно, некоторые другие параметры, и вы не будете запускать последнюю kill
— вы будете ждать dd
ее завершения самостоятельно.
Чтобы ответить на ваш последний вопрос, вот как вы посылаете USR1
сигналы из оболочки (или любой другой сигнал): вы используетеkill
с сигналом, который вы хотите отправить, и идентификаторами процесса (или идентификаторами задания) процессов, которым вы хотите отправить сигнал. Другие (не POSIX) команды, которые вы можете использовать, этоpkill
иkillall
, когда вы хотите найти процессы по имени.
решение3
Для большинства или всех оболочек $!
— это идентификатор процесса (также называемый PID) последнего процесса, который оболочка разветвила. Команда dd
разветвилась с помощью &
, так что справа pid=$!
после разветвления dd
назначается dd
идентификатор процесса переменной оболочки pid
.
Идентификатор процесса — это число, используемое Linux или Unix для обозначения адресного пространства, в котором выполняется некоторый код.
Программа kill
имеет неинтуитивное название, потому что ее цель — отправлять сигналы (небольшие, асинхронные сообщения) процессам. Есть только несколько сигналов, может быть, 128 в общей сложности, они имеют и номера, и имена. Сигнал «kill» имеет номер 9, например. USR1 определяется как номер 10. Таким образом, отправляет kill -USR1 $pid
сигнал 10 процессу с номером $pid
. dd
иногда требуется много времени для выполнения, так что это почти наверняка идентификатор процесса команды, dd
которая была разветвлена ранее и запущена в фоновом режиме. kill $pid
Команда отправляет сигнал TERM тому же идентификатору процесса. TERM означает «завершить». Хорошо написанные программы обычно перехватывают TERM, очищают выделенные им ресурсы и затем выходят.
Я не совсем уверен, почему вы работаете dd
в фоновом режиме, отправляете ему сигнал USR1, ждете 1 секунду, а затем вызываете dd
освобождение всех ресурсов и выход. Весь фрагмент кода, похоже, предполагает, что dd
он выполняется долгое время, что может быть не так. Я думаю, что в этом коде есть состояния гонки, и какой бы ни была желаемая семантика, вы можете их не получить.
решение4
Если вы ожидаете, dd
что команда будет запущена в фоновом режиме и отобразит текущий статус выполнения, попробуйте запустить команду с status=progress
флагом:
sudo dd if=/dev/sda of=/dev/sdb status=progress
Это позволит динамически отображать ход выполнения.
Это расширение реализации GNU dd
(добавлено в версии 8.24, выпущенной в 2015 году), также доступное в dd
реализации FreeBSD с версии 12.0 (2018), но, как правило, недоступное в других реализациях, в том числе в других BSD.