Удаленная переустановка Linux по ssh без доступа к консоли
Взято отсюда, поэтому сохранена практически полностью стилистика, но вырезано вступление.
Предупреждение! Надо понимать, что все, что мы будем делать — дорога в один конец, при ошибке мы теряем доступ к системе! Вполне возможно, что придется ехать 1500 километров и лезть в шахту, чтобы реанимировать сервер.
Будем считать, что IP нашей системы 192.168.56.102. Именно так было у меня на стенде. Плюс доступ к интернету через прокси:
http://proxy:8080
Начинаем работу на исходной системе.
# System #0
Заходим по ssh на сервер:
ssh 192.168.56.102
Создаем каталог и файловую систему для «Системы убийцы», монтируем её:
mkdir /target mount none -t tmpfs -o size=1G /target/
Ставим отличную утилиту debootstrap, которая разворачивает минимальную установку Debian, при помощи неё мы создадим chroot окружение:
export http_proxy='http://proxy:8080' apt-get -y install debootstrap
Существуют аналогичные утилиты для Федоры и Centos, соответственно febootstrap и yumbootstrap, но я с ними не работал.
Разворачиваем chroot:
debootstrap jessie /target/ http://mirror.mephi.ru/debian/
Первый аргумент — версия, второй — каталог установки, третий — репозиторий.
Бекапим самое необходимое:
mkdir /target/backup cp /etc/network/interfaces /target/backup
Самое важное — настройки сетевых интерфейсов, без них не получится попасть в переустановленную систему.
Даем имя chroot-окружению:
echo "Killer_system" > /target/etc/debian_chroot
Слово «Killer_system» будет показываться в приглашении bash. Это важная штука, без неё будет не понятно, где мы в данный момент находимся.
Переходим в новое окружение.
# System #1
chroot /target
Монтируем полезные fs:
mount none -t proc /proc/ mount none -t sysfs /sys/ mount none -t devtmpfs /dev/ mount none -t devpts /dev/pts/
Еще раз ставим debootstrap:
apt-get -y install lvm2 debootstrap
Дальше мои заморочки: у дебиановского пакета openssh-server в рекомендованных пакетах есть пакет xauth, а у него в зависимостях всякие иксовые библиотеки. Я, как сторонник минимализма, не хочу, чтобы на сервере, где не было и не будет графики, ставились огрызки иксов. Поэтому ставим с ключиком --no-install-recommends:
apt-get -y install openssh-server openssh-client openssh-blacklist openssh-blacklist-extra --no-install-recommends
Правим конфиги. Ставим альтернативный порт для ssh демона, чтобы мы могли зайти на chroot систему по ssh:
sed -i 's/^Port .*$/Port 11122/' /etc/ssh/sshd_config
И разрешаем доступ для root:
sed -i 's/^PermitRootLogin .*$/PermitRootLogin yes/' /etc/ssh/sshd_config /etc/init.d/ssh restart
Можно не давать доступ root, а создать пользователя и дать ему sudo права, но тут я сознательно упрощаю.
Дальше надо задать пароль root, так как по умолчанию debootstrap не устанавливает никакие пароли:
passwd root
Заходим в chroot окружение по ssh:
ssh 192.168.56.102 -l root -p 11122
Это мы делаем для того, чтобы полностью отвязаться от старой системы, у которой мы оторвем диски. А так у нас будет полностью автономная система в оперативной памяти, никак не связанная со старой.
Такой трюк очень хорошо подходит, если мы уходим от хостера, а оставлять ему наши файлы очень не хочется (я знаю, паранойя). На этом этапе просто забиваем диски нулями, если хотим быстро:
dd if=/dev/zero of=/dev/sda bs=1M
Или случайными данными в несколько проходов, если хотим хорошо. Достоинство метода в том, что мы можем дождаться окончания работы dd и, при необходимости, повторить. Если же затирать диски непосредственно из боевой системы, то посмотреть на результаты работы dd мы уже не сможем.
Попробуем простой путь, удалим тома и разделы:
# lvremove /dev/mapper/vg_old-root Logical volume vg_root/lv_root contains a filesystem in use.
# fdisk /dev/sda Command (m for help): d Selected partition 1 Partition 1 has been deleted. Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Re-reading the partition table failed.: Device or resource busy The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).
Но неудача. При этом раздел удалится, и система сломается, но воспользоваться простым путем без перезагрузки не получится. А перегружаться будет некуда.
Мы пойдем другим путем. Проверяем, где у нас что находится:
pvs lsblk
Будем считать, что корневой раздел у нас на диске sda. Затираем диск, чтобы ни в коем случае его не подцепил lvm.
Предупреждение! После этого момента возврата нет, даже следующий шаг не такой вредоносный. Задумаемся на минуту, проверим консоль, за которой сидим и оправдаем имя нашего chroot'а:
dd if=/dev/zero of=/dev/sda bs=1M count=100
Отрываем диски:
echo 1 > /sys/block/sda/device/delete
Проверяем, диск оторвался:
lsblk
Подключаем диск обратно:
for i in /sys/class/scsi_host/host?/scan ; do echo "- - -" > $i ; done
Проверяем, что вернулось:
lsblk
Был sda, стал sdb, отлично.
Важный момент: на згрузочном диске необходимо создать один первичный раздел размером на весь диск и этот раздел отдать lvm'у для того чтобы на него смог встать grub. Все остальные диски можно отдавать lvm'у целиком не создавая систему разделов (pvcreate /dev/sdc). Создаем таблицу разделов и один первичный раздел типа 8e, Linux LVM:
fdisk /dev/sdb n<CR> <CR> <CR> <CR> t<RC> 8e<CR> w<CR> # create new primary partition from start to end; 8e type
В первоначальной версии скрипта было создание одного логического тома под всю систему, но когда мой коллега переустанавливал Linux по этому скрипту, оказалось, что создание нескольких разделов представляет некоторую трудность, особенно отдельный раздел под логи. Внимание надо обратить на порядок создания точек монтирования и собственно монтирования разделов.
pvcreate /dev/sdb1 vgcreate vg_root /dev/sdb1 lvcreate -Zn -L500M -n lv_swap0 vg_root lvcreate -Zn -L1G -n lv_root vg_root lvcreate -Zn -L2G -n lv_usr vg_root lvcreate -Zn -L2G -n lv_var vg_root lvcreate -Zn -L1G -n lv_var_log vg_root lvcreate -Zn -L1G -n lv_home vg_root
mkswap /dev/vg_root/lv_swap0 mkfs.ext4 /dev/mapper/vg_root-lv_root mkfs.ext4 /dev/mapper/vg_root-lv_usr mkfs.ext4 /dev/mapper/vg_root-lv_var mkfs.ext4 /dev/mapper/vg_root-lv_var_log mkfs.ext4 /dev/mapper/vg_root-lv_home
mkdir /target mount /dev/mapper/vg_root-lv_root /target/ mkdir /target/usr /target/var /target/home mount /dev/mapper/vg_root-lv_usr /target/usr mount /dev/mapper/vg_root-lv_var /target/var mkdir /target/var/log mount /dev/mapper/vg_root-lv_var_log /target/var/log mount /dev/mapper/vg_root-lv_home /target/home
Разворачиваем уже боевую систему на новое место на жестком диске:
export http_proxy='http://proxy:8080' debootstrap jessie /target/ http://mirror.mephi.ru/debian/ echo "NEW_system" > /target/etc/debian_chroot
Возвращаем на место резервные копии конфигов:
cp /backup/interfaces /target/etc/network
Теперь нас ждет новая система:
# System #2
chroot /target
Обратите внимание, в приглашении командной строки теперь имя нового chroot окружения.
Монтируем файловые системы:
mount none -t proc /proc/ mount none -t sysfs /sys/ mount none -t devtmpfs /dev/ mount none -t devpts /dev/pts/
Ещё можно примонтровать эти файловые системы из родительского chroot'а:
mount -o bind /proc/ /target/proc mount -o bind /sys/ /target/sys mount -o bind /dev/ /target/dev mount -o bind /dev/pts /target/dev/pts
Устанавливаем и конфигурируем openssh:
apt-get -y install openssh-server openssh-client openssh-blacklist openssh-blacklist-extra --no-install-recommends
sed -i 's/^PermitRootLogin .*$/PermitRootLogin yes/' /etc/ssh/sshd_config passwd root
Устанавливаем пакеты, без которых не обойтись:
apt-get -y install vim sudo linux-image-3.16.0-4-amd64 grub2 lvm2 psmisc vlan
Да, я не могу жить без vim и ненавижу nano:
update-alternatives --set editor /usr/bin/vim.basic
В принципе grub прописывается куда надо ещё при установке, но, всё же, для поддержки штанов и морального духа повторим:
update-grub grub-install /dev/sdb
Теперь правим конфиги, вначале самый важный, без которого система не поднимется:
cat > /etc/fstab <<EOF # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # <file system> <mount point> <type> <options> <dump> <pass>
/dev/mapper/vg_root-lv_root / ext4 errors=remount-ro 0 1 /dev/mapper/vg_root-lv_usr /usr ext4 defaults 0 2 /dev/mapper/vg_root-lv_var /var ext4 defaults 0 2 /dev/mapper/vg_root-lv_var_log /var/log ext4 defaults 0 2 /dev/mapper/vg_root-lv_home /home ext4 defaults 0 2
EOF
В файле interfaces все должно быть в порядке, ведь как-то сеть у нас работала?
vim /etc/network/interfaces
В конфиг apt'а добавляем информацию о прокси:
echo 'Acquire::http::Proxy "http://proxy:8080";' > /etc/apt/apt.conf
Меняем hostname:
echo new-system > /etc/hostname
Добавляем строчку в /etc/hosts:
echo "192.168.56.102 new-system.corp new-system" >> /etc/hosts
Добавляем админа:
adduser admin usermod -a -G sudo admin visudo
Размонтируем файловые системы:
umount /dev/pts umount /dev/ umount /proc/ umount /sys/
И выходим из chroot'а:
exit
Размонтируем файловые системы:
umount /target/usr/ /target/var/log/ /target/var/ /target/home/
Если размонтировать /dev не удалось, то не удастся размонтировать и /target, но это не страшно.
Если удалось, то делаем так:
umount /target/
Если нет, то так:
sync ; sync ; sync ; mount -o remount,ro /target/
Эти команды сбросят дисковые кеши и перемонтируют корневую файловую систему в read only. После этого можно перегружаться.
Тут-то нас ждет сюрприз от всеми любимого systemd! Он знает, что мы в chroot и не дает перегрузиться! Google дает советы выйти из chroot, но нам-то выходить некуда. Но на помощь приходит Magic SysRq!
Активируем SysRq (он, скорее всего, активирован, но нам же надо убедиться?).
echo 1 > /proc/sys/kernel/sysrq
И перегружаемся:
echo b > /proc/sysrq-trigger
Барабанная дробь, тревожное ожидание, неужели мы что-то забыли, и сервер не поднялся?
ssh 192.168.56.102
Ура! Мы в новой системе!
Пересоздадим initrd. Это не обязательно, но в дальнейшем избавит от некоторых ошибок при перезагрузке:
update-initramfs -u
Удаляем файлик с именем chroot окружения:
rm /etc/debian_chroot
Вот и все.
The end