По аналогии с debootstrap, pacstrap, не найдя аналога для своего уютненького CRUX, решил заняться написанием сей утилиты. Приглашаю к тестированию.
Если у вас CRUX, она у вас будет работать из коробки (на самом деле нет). Если у вас другой дистрибутив, то вам в любом случае необходимо подготовить среду для развёртывания КРАКСИКОВ. Это как ФИКСИКИ, только КРАКСИКИ. :3
- Сохраняем эту портянку кода в ./cruxstrap (Внимание! Объявление: ищу хостинг).
- Скачиваем CRUX, последнюю версию, например отсюда: http://ftp.morpheus.net/pub/linux/crux/latest/iso/crux-3.5.iso
-
# mkdir /mnt/crux-install
-
# mount crux-3.5.iso /mnt/crux-install
— монтируем образ -
# cp -r /mnt/crux-install/crux/core .
— копируем порты, это установочные пакеты. Они нужны, чтобы КРАКСИКИ могли плодиться. -
# tar -C /tmp -x -f core/pkgutils/pkgutils#*.pkg.tar.xz usr/bin/pkgadd
- извлекаем pkgadd, необходимый для работы скрипта. - Всё готово, вы великолепны!
Запускать так:
# mkdir chroot/
# cruxstrap --pkgadd /tmp/usr/bin/pkgadd chroot/ core/
Где, chroot/ — это директория, куда будет установлен CRUX, core/ — это директория с пакетами, которые будут установлены. Если у вас CRUX, указывать путь до pkgadd и вообще извлекать его не нужно.
TODO: реализовать установку не всех подряд пакетов из директории, а возможность указывать их списком # cruxstrap chroot /usr/ports bash linux linux-firmware ...
#!/bin/bash
panic() {
if [ -d "$TMP" ]; then
rm -rf $TMP 2>/dev/null
fi
exit ${1:1}
}
got_cmdline() {
while [ "$1" ]; do
case "$1" in
-pa|--pkgadd) shift ; PKGADD_BIN="$1" ;;
-v|--version) echo "`basename $CRUXSTRAP_COMMAND` $CRUXSTRAP_VERSION" ; exit 0 ;;
-h|--help) got_help ; exit 0 ;;
*)
if [ -z "$CHROOT_DIR" ]; then
CHROOT_DIR="$1"
shift
continue
fi
if [ -z "$MIRROR_DIR" ]; then
MIRROR_DIR="$1"
shift
continue
fi
TO_INSTALL+=($1)
shift
;;
esac
done
}
search_in() {
for obj in $1/*; do
if [ -f "$obj" ]; then
case "$obj" in
*.pkg.tar.gz) echo $obj ;;
*.pkg.tar.bz2) echo $obj ;;
*.pkg.tar.xz) echo $obj ;;
*.pkg.tar.zstd) echo $obj ;;
esac
elif [ -d "$obj" ]; then
search_in $obj
fi
done
}
search_for() {
# TODO
echo
}
got_help() {
echo "usage: `basename $CRUXSTRAP_COMMAND` [options] new_chroot_dir/ /ports_dir [package ...]"
echo "options:"
echo " -pa, --pkgadd set path to pkgadd [/usr/bin/pkgadd]"
echo " -v, --version print version and exit"
echo " -h, --help print help and exit"
}
main() {
PKGADD_BIN="/usr/bin/pkgadd"
CHROOT_DIR=""
MIRROR_DIR=""
TO_INSTALL=()
got_cmdline "$@"
if [ ! -n "$CHROOT_DIR" ] || [ ! -n "$MIRROR_DIR" ]; then
got_help
exit 0
fi
if [ ! -x "$PKGADD_BIN" ]; then
echo "Can't find $PKGADD_BIN, try add: --pkgadd ./pkgadd"
panic
fi
if [ ! -d "$CHROOT_DIR" ]; then
echo "'$CHROOT_DIR' is not directory."
panic
fi
if [ ! -d "$MIRROR_DIR" ]; then
echo "'$MIRROR_DIR' is not directory."
panic
fi
if [ ! -z "$TO_INSTALL" ]; then
SEARCH_FOR=$TO_INSTALL
TO_INSTALL=()
for pkg in ${SEARCH_FOR[@]}; do
TO_INSTALL+=($(search_for $MIRROR_DIR $pkg))
done
else
TO_INSTALL=($(search_in $MIRROR_DIR))
fi
if [ ! -n "$TO_INSTALL" ]; then
echo "Nothing to do. Check for $MIRROR_DIR dir."
panic
fi
for db in $CHROOT_DIR/var/lib/pkg{,/db}; do
case "$db" in
*/var/lib/pkg) install -d $db ;;
*/var/lib/pkg/db) touch $db ;;
esac
if [ $? = 0 ]; then
echo Database connected: $db
else
echo Unable to connect: $db
panic
fi
done
for pkg in ${TO_INSTALL[@]}; do
echo -n "Installing ${pkg##*/} ..."
$PKGADD_BIN --root $CHROOT_DIR $pkg 2>&1 >$TMP/log
if [ "$?" = "0" ]; then
echo " OK"
else
echo " ERROR"
cat $TMP/log
fi
done
}
trap "panic" INT HUP QUIT TERM EXIT
readonly CRUXSTRAP_COMMAND="$0"
readonly CRUXSTRAP_VERSION="0.1"
TMP="$(mktemp -d)"
main "$@"
Картинка для привлечения внимания.
Напоследок, дисклеймер, зачем это не нужно. В данный момент я разворачиваю куда более грандиозную систему по автоматизации сборки образов для виртуальных (и не только) машин. CRUXSTRAP лишь вершина, оно создаёт ванильный, это важно, chroot, который затем упаковывается в squashfs. Рядом с ним кладётся другой squashfs, в котором лежат только настройки системы (при загрузке системы настройки ложатся «поверх» через overlay). Вся эта порнография упаковывается в общий initramfs, которые вместе с vmlinuz по итогу отдаются по сети (PXE) на любые устройства в сети.
Всё это именуется общими названиями: [default], [internet-gateway], [mailer-daemon]... При загрузке DHCPD + TFTP отдают GRUB2, который пытается загрузить grub.cfg глядя на MAC-адрес:
set default=0
set timeout=0
set menu_color_highlight=white/dark-gray
set menu_color_normal=black/light-gray
set color_normal=light-blue/blue
regexp --set=1:m1 --set=2:m2 --set=3:m3 --set=4:m4 --set=5:m5 --set=6:m6 '^([0-9a-f]{1,2})\:([0-9a-f]{1,2})\:([0-9a-f]{1,2})\:([0-9a-f]{1,2})\:([0-9a-f]{1,2})\:([0-9a-f]{1,2})' "$net_pxe_mac"
set mac="${m1}-${m2}-${m3}-${m4}-${m5}-${m6}"
source /os/mac-$mac/grub.cfg
if [ "$default" = "0" ]; then
source /os/pxe-default/grub.cfg
fi
Если конфигурации с таким MAC не предусмотрено, отдаётся /os/pxe-default. Просто делаем ln -sf pxe-internet-gateway mac-52-54-00-12-34-56
, и теперь вместо /os/pxe-default машина с этим адресом пройдёт по симлинку и получит конфигурацию /os/pxe-internet-gateway. grub.cfg:
set default="pxe-internet-gateway"
menuentry "Configuration [internet-gateway] for ${net_pxe_ip} (${net_pxe_mac})" --id=pxe-internet-gateway --unrestricted {
linux /os/pxe-internet-gateway/vmlinuz
initrd /os/pxe-internet-gateway/initrd
}
Таким образом любой хост в сети может выполнять любую задачу, получив соответствующую конфигурацию.
В случае поломки софта или атаки хакеров, ты нажимаешь кнопочку Reset или ПОПРОБУЙТЕ ВЫКЛЮЧИТЬ И СНОВА ВКЛЮЧИТЬ, система загружается по сети с нуля, как ни в чём небывало.
В случае поломки железа, ты даже не заморачиваешься, включаешь в сеть другую железку, меняешь её аки лампочку в цоколе, и всего-навсего прописываешь ln -sf новый MAC, чтобы теперь эта железка выполняла такую-то роль в сети. И всё. А представьте, если вы создадите систему которая масштабируется by-design. Загружается и автоматически становится частью чего-то, нодой. Один раз настроил у себя ОС для неё, и только и успевай подключать новые железки! Уххх. :D
Вся настройка, всех хостов лежит на твоей стороне. Структура:
/var/tftpboot/os/mac-00-00-00-00-00-00 -> /var/tftpboot/os/pxe-default
/var/tftpboot/os/mac-52-54-00-12-34-56 -> /var/tftpboot/os/pxe-internet-gateway
/var/tftpboot/os/pxe-default/grub.cfg
/var/tftpboot/os/pxe-default/vmlinuz
/var/tftpboot/os/pxe-default/initrd
/var/tftpboot/os/pxe-default/packages
/var/tftpboot/os/pxe-default/packages/bash#5.0.17-1.pkg.tar.xz -> /usr/ports/core/bash/bash#5.0.17-1.pkg.tar.xz
/var/tftpboot/os/pxe-default/packages/linux#5.6.7-1.pkg.tar.gz -> /root/ports/linux/linux#5.6.7-1.pkg.tar.gz
...
/var/tftpboot/os/pxe-default/persistent
/var/tftpboot/os/pxe-default/persistent/etc
/var/tftpboot/os/pxe-default/persistent/etc/rc.conf
/var/tftpboot/os/pxe-default/persistent/etc/ssh
/var/tftpboot/os/pxe-default/persistent/etc/ssh/sshd_config
Для каждого хоста свои пакеты, своя конфигурация. Обновил конфигурацию, пересобрал образ, перезагрузил хост. Не важно, виртуальная это машина или стационарный ПК.
И не важно, это может быть не CRUX, а любой другой дистрибутив, собранный в chroot: он точно так же будет упакован в squashfs, со своими настройками, и будет загружаться по сети со своим ядром.
P.S.: А чём вы занимаетесь на карантине?