Вопрос или проблема
Я пытаюсь создать правило udev, которое монтирует мое устройство по его uuid, чтобы я мог затем прочитать его содержимое.
Мой файл udev находится в /etc/udev/rules.d/99-local.rules
, и вот его содержимое:
ACTION=="add", ENV{ID_FS_UUID}=="12CB-F616", SYMLINK+="masterkey", RUN+="/usr/bin/mountkey.sh"
Скрипт, запускаемый правилом udev, состоит из следующего:
LOG_FILE="/tmp/mount-key.log"
mount /dev/masterkey /mnt/masterkey > "$LOG_FILE"
MOUNT_POINT="$(findmnt -n -o TARGET --source '/dev/masterkey')"
echo "Device mounted at $MOUNT_POINT" >> "$LOG_FILE"
Проблема в том, что когда udev вызывает команду mount, она, похоже, не работает, и команда не производит никакого вывода, как и переменная окружения MOUNT_POINT в файле лога. Даже несмотря на то, что udev действительно создает символьную ссылку masterkey.
Файл лога выглядит так:
Device mounted at
Я подтвердил, что раздел действительно не смонтирован после выполнения lsblk
:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 1 3.8G 0 disk
└─sda1 8:1 1 3.8G 0 part
...
Я изменил скрипт и вместо этого запустил его с sudo, но получил тот же вывод, что и выше. Затем я решил запустить команду mount от имени root без ввода пароля (думая, что в этом была проблема), я отредактировал файл /etc/sudoers
с помощью visudo и добавил строку с полем NOPASSWD для mount для пользователя root, вот так:
root ALL=(ALL:ALL) ALL
root ALL=NOPASSWD:/usr/bin/mount
Также я попробовал запустить это различными способами:
ACTION=="add", ENV{ID_FS_UUID}=="12CB-F616", SYMLINK+="masterkey", RUN+="/bin/bash -c '/usr/bin/mountkey.sh'"
ACTION=="add", ENV{ID_FS_UUID}=="12CB-F616", SYMLINK+="masterkey", RUN+="/bin/bash -c 'sudo /usr/bin/mount /dev/masterkey /mnt/masterkey'"
ACTION=="add", ENV{ID_FS_UUID}=="12CB-F616", SYMLINK+="masterkey", RUN+="/bin/bash -c '/usr/bin/mount /dev/masterkey /mnt/masterkey'"
Я пробовал делать все это с sh (с #!/bin/sh) и никакой из этих способов не сработал. Похоже, нет проблемы с вызовом скрипта и созданием символьной ссылки, но проблема возникает при запуске бинарного файла mount любым методом.
И дело не в моем бинарном файле mount, потому что когда я запускаю:
sudo mount /dev/sdnx /mnt/masterkey
он работает корректно.
После многих попыток без намека на то, в чем может быть проблема, я изменил правило udev следующим образом:
ACTION=="add", ENV{ID_FS_UUID}=="12CB-F616", RUN+="/bin/bash -c '/usr/local/bin/mountkey.sh $ID_FS_UUID'"
И мой bash-скрипт:
#!/bin/bash
UUID="$1"
DEVICE=$(blkid -o device -t UUID="$UUID")
echo "$UUID\n$DEVICE" > "/tmp/mountkey.log"
mount $DEVICE /media/masterkey
Но о, сюрприз, ничего не изменилось.
ВИРТУАЛЬНАЯ МАШИНА
Vagrant (archlinux/archlinux)
Ядро 6.10.10-arch1-1
РЕАЛЬНАЯ СИСТЕМА
Я попытался запустить правило udev на своей реальной машине, которая:
Arch linux / 6.13.2-arch1-1
Но я все равно получил тот же результат (раздел в системе не смонтирован).
Таким образом, сделав это, я подтвердил, что проблема заключается в одном из файлов (правило udev или bash-скрипт).
Ответ или решение
Теория
Для понимания проблем, связанных с монтированием устройств с помощью udev и BASH-скриптов, необходимо учитывать особенности работы udev, ограничения контекста, в котором он работает, и потенциоальные ошибки конфигурации. Udev, как система управления устройствами, запускается в фоновом режиме и является частью init system; в большинстве современных систем это systemd. Приложения и скрипты, запускаемые через udev, работают в строго ограниченном окружении без доступа к пользовательским правам или переменным окружения.
Однако, помимо ограничения на доступ к пользовательским окружениям, udev также располагает своими особенностями в обработке системных команд:
- Ограниченное окружение: Udev не наследует окружение пользователя, поэтому решения на основе переменных окружения, таких как
$PATH
, могут не работать. - Поток вывода: Udev ожидает, что скрипты завершат работу за определенное время, и в случае задержек или ожидания вывода могут возникать проблемы.
- Операции с диском: Операции с файлами и подсистемами ввода-вывода могут быть затруднены из-за недостаточного времени выполнения или доступа.
Пример
Рассмотрим, как можно протестировать и исправить проблемы с udev на примере предоставленных udev-правил и BASH-скрипта.
Вы определили правило udev следующим образом:
ACTION=="add", ENV{ID_FS_UUID}=="12CB-F616", SYMLINK+="masterkey", RUN+="/usr/bin/mountkey.sh"
И соответствующий BASH-скрипт:
#!/bin/bash
LOG_FILE="/tmp/mount-key.log"
mount /dev/masterkey /mnt/masterkey > "$LOG_FILE"
MOUNT_POINT="$(findmnt -n -o TARGET --source '/dev/masterkey')"
echo "Device mounted at $MOUNT_POINT" >> "$LOG_FILE"
Применение
1. Устройства и права доступа
Убедитесь, что устройство правильно идентифицируется с помощью lsblk
и подтверждено, что оно действительно имеет UUID 12CB-F616
. Например:
lsblk -f | grep '12CB-F616'
Если есть несоответствия, udev не сможет вызвать скрипт корректно.
2. Пересечение требований прав
Запуск mount
требует root-прав. В udev важно использовать прямое указание нужных параметров. Пропишите в скрипте:
sudo mount /dev/sda1 /mnt/masterkey
Убедитесь, что sudoers правильно настроены для выполнения команды без пароля:
root ALL=(ALL:ALL) NOPASSWD: /usr/bin/mount /dev/sda1 /mnt/masterkey
3. Тестирование в терминале
Перед тестированием через udev, отладьте скрипт в терминале:
sudo /usr/bin/mountkey.sh
Если ошибки отсутствуют, переходите к отладке через udev.
4. Проверка прав доступа и лога
Логирование—ключевой момент в анализе ошибок. Добавьте отладочную информацию в лог, например, вывод ошибки от mount
:
mount /dev/masterkey /mnt/masterkey 2>> "$LOG_FILE"
Также добавьте больше логов в скрипт для увеличения прозрачности выполнения на каждом этапе процесса.
5. Обновление правил udev
После изменений нужно освежить правила:
udevadm control --reload-rules
udevadm trigger
6. Тестирование в изолированном окружении
Создайте виртуальное окружение или VM для проверки готовности правил:
Используйте те же команды и проверьте, работает ли все в свежем окружении.
Исправив указанные несоответствия и внедрив практики тестирования, вы сможете больше влиять на управление устройствами через udev. Проблемы с udev часто связаны с разрешениями и ограниченной средой, но подробное логгирование и тесты помогают быстро их диагностировать и решать.