Chroot: различия между версиями
Klark (обсуждение | вклад) |
Klark (обсуждение | вклад) |
||
Строка 53: | Строка 53: | ||
(CHROOT) $PS1# umount /proc || umount -l /proc | (CHROOT) $PS1# umount /proc || umount -l /proc | ||
(CHROOT) $PS1# exit | (CHROOT) $PS1# exit | ||
hostname <исходный_хост> | |||
$PS1# umount /mnt/target/dev || umount -l /mnt/target/dev | $PS1# umount /mnt/target/dev || umount -l /mnt/target/dev | ||
$PS1# umount /mnt/target || umount -l /mnt/target | $PS1# umount /mnt/target || umount -l /mnt/target |
Версия от 03:55, 31 марта 2018
Чрут (команда chroot, от англ. change root) - это временная смена корня. Может выполняться с разными целями. Например, загружаемся с ALT Rescue флэшки и чиним поломанную систему или меняем забытый пароль пользователя root, для чего монтируем корень целевой системы и делаем в него чрут. Все нижеописанные действия требуют полномочий пользователя root.
Подготовка к переходу в целевую систему
mkdir /mnt/target
mount /dev/sda2 /mnt/target
cp -Lf /etc/resolv.conf /mnt/target/etc/
mount --bind /dev /mnt/target/dev
hostname <целевой_хост>
Предполагается, что корень целевой системы находится во втором разделе первого диска (/dev/sda2). Перед тем, как сменить корень, мы уже подняли сеть. Но, чтобы в чруте работало преобразование имён в IP-адреса (и обратно), мы скопировали текущий /etc/resolv.conf, например, на случай, если будем ставить пакеты из сети.
Также мы сделали bind-mount ВСЕХ устройств из исходной системы. Все необходимые устройства должны быть в будущем /dev. bind-mount решает эту задачу одной командой, потому что, как правило, в исходной системе все имеющиеся устройства уже доступны через devtmpfs в /dev. Однако, если мы не доверяем этому чруту, не хотим, чтобы из него можно было оказать негативное воздействие на исходную систему, из которой мы заходим в этот чрут, то делать bind-mount напротив, не следует. Достаточно вручную определить в /mnt/target/dev только необходимые ноды устройств (man mknod).
Последней командой мы переустановили hostname. Если имя хоста выводится в приглашении, то во время работы в чруте имя будет ожидаемым. Также это необходимо для работы с некоторыми утилитами, привязывающимися к имени хоста, например, mdadm. Не забывайте вернуть оригинальный hostname по возвращении в исходную систему!
Переход в целевую систему
PS1="(CHROOT) $PS1" chroot /mnt/target /bin/bash
В простом случае так. PS1 рекомендуется менять, чтобы визуально отличать приглашение в чруте от приглашений в других терминалах. Вместо /bin/bash можно указать свою любимую оболочку. Предлагаемый выше вызов как бы перенесёт вас в целевую систему, в точку, когда система с ядром и initrd уже загрузились, когда запустились все службы, когда было дано дано приглашение войти в систему, разве что без ввода логина и пароля. На самом деле ничего этого, конечно, не было, просто при запуске процесс /bin/bash получил в качестве "корневой" директорию /mnt/target. Ни /bin/bash, ни что-либо из него запущенное не смогут увидеть директории выше уровнем, им доступно только содержимое /mnt/target, которое они видят как "/". Но есть ещё один существенный нюанс. Команда выше передаёт все переменные окружения из исходной системы, а это далеко не всегда желательно. Более длинный, но более безопасный вариант запуска мог бы выглядеть следующим образом:
chroot /mnt/target /usr/bin/env -i PS1="(CHROOT) $PS1" LANG=C \
PATH="$PATH" HOME="/root" USER="root" TERM="linux" LC_ALL=C /bin/bash
Здесь мы очищаем ВСЕ переменные среды для новой оболочки и устанавливаем всего несколько переменных, передавая им определённые значения. Такой подход позволит избежать всевозможных side-эффектов при дальнейшей работе в чруте. Другой нюанс заключается в том, что с высокой вероятностью мы загрузились с ДРУГОЙ версией ядра, возможно даже из ДРУГОГО дистрибутива GNU/Linux. Команды типа uname -r, uanme -a покажут всё верно, то бишь информацию о реально загруженном ядре, на которую ориентируются такие скрипты, как make-initrd. По умолчанию они просто выругаются, не найдя такого ядра в вашем чруте, поэтому их нужно запускать иначе:
make-initrd -f <ваше-ядро-в-чруте>
Первым делом в целевой системе
mount /proc
mount /dev/pts
mount -t sysfs none /sys
Отнюдь не всё это может потребоваться. Если какая-то программа ругается, что ей нужен sysfs, например, lspci без него работать не станет, можно смонтировать и позже, по мере необходимости. Если хотите понять, почему первые две команды выше имеют сокращённую форму, а третья команда - полную форму, загляните в /etc/fstab. Что характерно для ALT Linux, может быть совершенно иначе в других дистрибутивах. Не забывайте об этом, чрутясь куда-то не туда. :)
Выход из целевой системы
(CHROOT) $PS1# umount /sys || umount -l /sys
(CHROOT) $PS1# umount /dev/pts || umount -l /dev/pts
(CHROOT) $PS1# umount /proc || umount -l /proc
(CHROOT) $PS1# exit
hostname <исходный_хост>
$PS1# umount /mnt/target/dev || umount -l /mnt/target/dev
$PS1# umount /mnt/target || umount -l /mnt/target
$PS1# rmdir /mnt/target
Не забываем отмонтировать всё, что было смонтировано ранее. Обращаем внимание на синтаксис.
Чрут в экзотическую систему
В случае, если в целевой системе отсутствует команда mount, что совсем не характерно для ALT Linux, смонтировать в ней /proc, /sys и /dev/pts не получится. Тогда придётся сделать это заранее до перехода в экзотический чрут.
mount -t proc none /mnt/target/proc
mount -t sysfs none /mnt/target/sys
mount -t devpts none /mnt/target/dev/pts
либо так:
mount --bind /proc /mnt/target/proc
mount --bind /sys /mnt/target/sys
mount --bind /dev/pts /mnt/target/dev/pts
Хотя последняя форма наиболее универсальная, есть целый ряд причин, по которым предпочтительно монтировать эти три файловые системы только по мере необходимости, и только изнутри самого чрута.
Кроме того, возможен чрут из 64-бит исходной системы в 32-бит целевую систему. В ALT Linux для этих целей используется setarch.
setarch i586 chroot /mnt/target /usr/bin/env -i PS1="(CHROOT) $PS1" LANG=C \
PATH="$PATH" HOME="/root" USER="root" TERM="linux" LC_ALL=C /bin/bash
При отсутствии /usr/bin/env в целевой системе, что также не характерно для ALT Linux, достаточно поменять аргументы местами, например:
/usr/bin/env -i PS1="(CHROOT) $PS1" LANG=C PATH="$PATH" HOME="/root" \
USER="root" TERM="linux" LC_ALL=C chroot /mnt/target /bin/bash
Enjoy! ;-)