Chroot: различия между версиями
Klark (обсуждение | вклад) |
Илья Н. (обсуждение | вклад) м (Убрал ссылку) |
||
(не показано 27 промежуточных версий 4 участников) | |||
Строка 1: | Строка 1: | ||
Чрут (команда [https://ru.wikipedia.org/wiki/Chroot chroot], от англ. '''change root''') - это временная смена корня. Может выполняться с разными целями. Например, загружаемся с [[Rescue|ALT Rescue]] флэшки и чиним поломанную систему, для чего монтируем корень | Чрут (команда [https://ru.wikipedia.org/wiki/Chroot chroot], от англ. '''change root''') - это временная смена корня. Может выполняться с разными целями. Например, загружаемся с [[Rescue|ALT Rescue]] флэшки и чиним поломанную систему или меняем забытый пароль пользователя '''root''', для чего монтируем корень целевой системы и делаем в него чрут. Все нижеописанные действия требуют полномочий пользователя '''root'''. | ||
=== Подготовка к переходу в целевую систему === | === Подготовка к переходу в целевую систему === | ||
Строка 8: | Строка 8: | ||
cp -Lf /etc/resolv.conf /mnt/target/etc/ | cp -Lf /etc/resolv.conf /mnt/target/etc/ | ||
mount --bind /dev /mnt/target/dev | mount --bind /dev /mnt/target/dev | ||
hostname <целевой_хост> | |||
</source> | </source> | ||
Предполагается, что корень целевой системы находится во втором разделе первого диска ('''/dev/sda2'''). Перед тем, как сменить корень, мы уже подняли сеть. Но, чтобы в чруте работало преобразование имён в IP-адреса, мы скопировали текущий '''/etc/resolv.conf''', например, на случай, если будем ставить пакеты из сети. Также мы сделали bind-mount ВСЕХ устройств из исходной системы. Все необходимые устройства должны быть в будущем /dev. '''bind-mount''' решает эту задачу одной командой, потому что, как правило, в исходной системе все имеющиеся устройства уже доступны через '''devtmpfs''' в '''/dev'''. Однако, если мы не доверяем этому чруту, не хотим, чтобы из него можно было оказать негативное воздействие на исходную систему, из которой мы заходим в этот чрут, то делать bind-mount напротив, не следует. Достаточно вручную определить в '''/mnt/target/dev''' только необходимые ноды устройств ('''man mknod'''). | Предполагается, что корень целевой системы находится во втором разделе первого диска ('''/dev/sda2'''). Перед тем, как сменить корень, мы уже подняли сеть. Но, чтобы в чруте работало преобразование имён в IP-адреса (и обратно), мы скопировали текущий '''/etc/resolv.conf''', например, на случай, если будем ставить пакеты из сети. | ||
Также мы сделали bind-mount ВСЕХ устройств из исходной системы. Все необходимые устройства должны быть в будущем /dev. '''bind-mount''' решает эту задачу одной командой, потому что, как правило, в исходной системе все имеющиеся устройства уже доступны через '''devtmpfs''' в '''/dev'''. Однако, если мы не доверяем этому чруту, не хотим, чтобы из него можно было оказать негативное воздействие на исходную систему, из которой мы заходим в этот чрут, то делать bind-mount напротив, не следует. Достаточно вручную определить в '''/mnt/target/dev''' только необходимые ноды устройств ('''man mknod'''). | |||
Последней командой мы переустановили '''hostname'''. Если имя хоста выводится в приглашении, то во время работы в чруте имя будет ожидаемым. Также это необходимо для работы с некоторыми утилитами, привязывающимися к имени хоста, например, '''mdadm'''. Не забывайте вернуть оригинальный '''hostname''' по возвращении в исходную систему! | |||
=== Переход в целевую систему === | === Переход в целевую систему === | ||
Строка 18: | Строка 23: | ||
</source> | </source> | ||
В простом случае так. '''PS1''' рекомендуется менять, чтобы визуально отличать приглашение в чруте от приглашений в других терминалах. Вместо '''/bin/bash''' можно указать '''свою любимую оболочку'''. Предлагаемый выше вызов '''как бы''' перенесёт вас в целевую систему, в точку, когда система с ядром и initrd уже | В простом случае так. '''PS1''' рекомендуется менять, чтобы визуально отличать приглашение в чруте от приглашений в других терминалах. Вместо '''/bin/bash''' можно указать '''свою любимую оболочку'''. Предлагаемый выше вызов '''как бы''' перенесёт вас в целевую систему, в точку, когда система с ядром и initrd уже загрузились, когда запустились все службы, когда было дано дано приглашение войти в систему, разве что без ввода логина и пароля. На самом деле ничего этого, конечно, не было, просто при запуске процесс '''/bin/bash''' получил в качестве "корневой" директорию '''/mnt/target'''. Ни /bin/bash, ни что-либо из него запущенное не смогут '''увидеть''' директории выше уровнем, им доступно только содержимое '''/mnt/target''', которое они видят как "/". Но есть ещё один существенный нюанс. Команда выше передаёт все переменные окружения из исходной системы, а это далеко не всегда желательно. Более длинный, но более безопасный вариант запуска мог бы выглядеть следующим образом: | ||
<source lang="text"> | <source lang="text"> | ||
Строка 25: | Строка 30: | ||
</source> | </source> | ||
Здесь мы очищаем ВСЕ переменные среды для новой оболочки и устанавливаем всего несколько переменных, передавая им '''определённые''' значения. Такой подход позволит избежать всевозможных side-эффектов при дальнейшей работе в чруте. Другой нюанс заключается в том, что с высокой вероятностью мы загрузились с ДРУГОЙ версией ядра, возможно даже из | Здесь мы очищаем ВСЕ переменные среды для новой оболочки и устанавливаем всего несколько переменных, передавая им '''определённые''' значения. Такой подход позволит избежать всевозможных side-эффектов при дальнейшей работе в чруте. Другой нюанс заключается в том, что с высокой вероятностью мы загрузились с ДРУГОЙ версией ядра, возможно даже из ДРУГОГО дистрибутива GNU/Linux. Команды типа '''uname -r''', '''uanme -a''' покажут всё верно, то бишь информацию о реально загруженном ядре, на которую ориентируются такие скрипты, как '''make-initrd'''. По умолчанию они просто выругаются, не найдя такого ядра в вашем чруте, поэтому их нужно запускать иначе: | ||
<source lang="text"> | <source lang="text"> | ||
make-initrd - | make-initrd -k <ваше-ядро-в-чруте> | ||
</source> | </source> | ||
=== Первым делом в целевой системе === | === Первым делом в целевой системе === | ||
Первая и наиболее предпочтительная форма подключения '''/proc''', '''/sys''' и '''/dev/pts'''. ''Про другие варианты говорится далее...'' | |||
<source lang="text"> | <source lang="text"> | ||
Строка 39: | Строка 46: | ||
</source> | </source> | ||
Отнюдь не всё это может потребоваться. Если какая-то программа ругается, что ей нужен sysfs, например, lspci без него работать не станет, можно смонтировать и | Отнюдь не всё это может потребоваться. Если какая-то программа ругается, что ей нужен '''sysfs''', например, '''lspci''' без него работать не станет, можно смонтировать и позже, по мере необходимости. Если хотите понять, почему первые две команды выше имеют сокращённую форму, а третья команда - полную форму, загляните в '''/etc/fstab'''. Что характерно для '''ALT Linux''', может быть совершенно иначе в других дистрибутивах. Не забывайте об этом, чрутясь куда-то не туда. :) | ||
=== Выход из целевой системы === | |||
=== Выход из | |||
<source lang="text" highlight="4"> | <source lang="text" highlight="4"> | ||
Строка 57: | Строка 55: | ||
(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 | ||
Строка 63: | Строка 62: | ||
Не забываем отмонтировать всё, что было смонтировано ранее. Обращаем внимание на синтаксис. | Не забываем отмонтировать всё, что было смонтировано ранее. Обращаем внимание на синтаксис. | ||
=== Чрут в экзотическую систему === | |||
В случае, если в целевой системе отсутствует команда '''mount''', что совсем не характерно для '''ALT Linux''', смонтировать в ней '''/proc''', '''/sys''' и '''/dev/pts''' не получится. Тогда придётся сделать это заранее до перехода в ''экзотический'' чрут. | |||
<source lang="text"> | |||
mount -t proc none /mnt/target/proc | |||
mount -t sysfs none /mnt/target/sys | |||
mount -t devpts none /mnt/target/dev/pts | |||
</source> | |||
либо так: | |||
<source lang="text"> | |||
mount --bind /proc /mnt/target/proc | |||
mount --bind /sys /mnt/target/sys | |||
mount --bind /dev/pts /mnt/target/dev/pts | |||
</source> | |||
Хотя последняя форма наиболее универсальная, есть целый ряд причин, по которым предпочтительно монтировать эти три файловые системы только по мере необходимости, и только изнутри самого чрута. | |||
Кроме того, возможен чрут из '''64-бит''' исходной системы в '''32-бит''' целевую систему. В '''ALT Linux''' для этих целей используется '''setarch'''. | |||
<source lang="text"> | |||
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 | |||
</source> | |||
При отсутствии '''/usr/bin/env''' в целевой системе, что также не характерно для '''ALT Linux''', достаточно поменять аргументы местами, например: | |||
<source lang="text"> | |||
/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 | |||
</source> | |||
=== А можно ли попроще? === | |||
Да, можно. Так как мы используем [[Rescue|ALT Rescue]], то сразу после загрузки нам доступен скрипт mount-system (о чём будет подсказка). Делаем так: | |||
mount-system | |||
chroot /mnt/system1 | |||
Если что-то пошло не так, то переходим к началу статьи. | |||
И чтобы отмонтировать: | |||
unmount-system | |||
'''Enjoy!''' ;-) | |||
{{Category navigation|title=Восстановление|category=Rescue|sortkey={{SUBPAGENAME}}}} | |||
[[Категория:HOWTO]] | [[Категория:HOWTO]] |
Текущая версия от 21:17, 7 октября 2024
Чрут (команда 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 -k <ваше-ядро-в-чруте>
Первым делом в целевой системе
Первая и наиболее предпочтительная форма подключения /proc, /sys и /dev/pts. Про другие варианты говорится далее...
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
А можно ли попроще?
Да, можно. Так как мы используем ALT Rescue, то сразу после загрузки нам доступен скрипт mount-system (о чём будет подсказка). Делаем так:
mount-system chroot /mnt/system1
Если что-то пошло не так, то переходим к началу статьи.
И чтобы отмонтировать:
unmount-system
Enjoy! ;-)