Poproszę jeszcze o walnięcie ocenki dla skryptu.
EDIT proszę moda o przeniesienie także tego wątku :)
Kod:
#!/bin/bash
set -o errexit
# set -o pipefail
# set -o nounset
# set -o xtrace
readonly lockdir=/tmp/prepare_zfs.lock
if ! mkdir "$lockdir"; then
die "Lock file already exists"
fi
trap 'stty echo; rm -rf "${lockdir}"; exit $?' EXIT
die() {
local msg=$1
printf "Error: %s. Exiting...\n" "$msg" >&2
exit 1
}
log_info() {
local msg=$1
printf "[INFO] %s...\n" "$msg"
}
require_binary() {
local binaries=( "$@" )
for binary in ${binaries[*]}; do
if ! command -v "${binary}" &> /dev/null; then
die "${binary} binary does not exist"
fi
done
}
display_usage() {
cat <<EOF
./bootstrap.sh - Bootstrap the Gentoo desktop base system
Usage:
./bootstrap.sh [ options ]
./bootstrap.sh --help\n"
Options:\n"
--cpus value (default: $(nproc)) - maximum available CPU cores
-m|--mnt path (default: /mnt/gentoo) - rootfs mount path
-u|--username value (default: user) - target system username
--hostname value (default: gentoo) - target system hostname
--domain value (default: lan) - target system domain
--load-percentage value (default: 0.75) - expected maximum load average
-j|--jobs value (default: unset) - how many jobs should portage use
--timezone value (default: UTC) - target system timezone
--locale value (default: en_US) - target system locale
--l10n value (default: en) - decides which extra localization support will be installed
--keymap value (default: en) - target system keymap
--profile|--gentoo-profile value (default: default/linux/amd64/17.1) - Gentoo profile
--zfs - specify this option if rootfs is on ZFS
--zfs-rpool value (default: rpool) - root ZFS pool
--zfs-bpool value (default: unset) - boot ZFS pool
--root-dev|--root-devs value - target root devices
--gentoo-mirrors|--mirrors value (default: https://gentoo.osuosl.org/) - specify Gentoo mirrors
--video-cards value (default: intel) - target system video cards
--base-system path (default: /root/stage3-*.tar.xz) - path to tarball with stage3
--distfiles-dir value (default: unset) - path to the distfiles directory
--tmpfs-enabled - enable tmpfs in /etc/fstab
--use|--use-flags values (default: verify-sig rsync-verify) - global USE flags
--accept-license \"value\" (default: -* @FREE)
--hwclock|--hardware-clock value (default: UTC)
-h|--help - displays usage
EOF
exit 0
}
while (( $# )); do
opt=$1
case $opt in
--cpus)
CPUS="$2"
shift 2
;;
-m|--mnt)
MNT_PATH="$2"
shift 2
;;
-u|--username)
TARGET_USERNAME="$2"
shift 2
;;
--hostname)
TARGET_HOSTNAME="$2"
shift 2
;;
--domain)
TARGET_DOMAIN="$2"
shift 2
;;
-l|--load-percentage)
LOAD_PERCENTAGE="$2"
shift 2
;;
-j|--jobs)
JOBS="$2"
shift 2
;;
--timezone)
TIMEZONE="$2"
shift 2
;;
--locale)
LOCALE="$2"
shift 2
;;
--l10n)
L10N="$2"
shift 2
;;
--keymap)
KEYMAP="$2"
shift 2
;;
--profile|--gentoo-profile)
GENTOO_PROFILE="$2"
shift 2
;;
--zfs)
ZFS_ENABLED="y"
shift 1
;;
--zfs-rpool)
ZFS_RPOOL="$2"
shift 2
;;
--zfs-bpool)
ZFS_BPOOL="$2"
shift 2
;;
--root-dev|root-devs)
ROOT_DEV="$2"
shift 2
;;
--gentoo-mirrors|--mirrors)
GENTOO_MIRRORS="$2"
shift 2
;;
--video-cards)
VIDEO_CARDS="$2"
shift 2
;;
--base-system)
BASE_SYSTEM="$2"
shift 2
;;
--distfiles-dir)
DISTFILES_DIR="$2"
shift 2
;;
--tmpfs-enabled)
TMPFS_ENABLED="y"
shift 1
;;
--use|--use-flags)
USE="$2"
shift 2
;;
--accept-license)
ACCEPT_LICENSE="$2"
shift 2
;;
--hwclock|--hardware-clock)
HWCLOCK="$2"
shift 2
;;
-h|--help)
display_usage
shift 1
;;
**)
printf "./bootstrap.sh: error: unrecognized arguments: %s" "$@"
display_usage
exit 1
;;
esac
done
CPUS=${CPUS:-$(nproc)}
MNT_PATH=${MNT_PATH:-/mnt/gentoo}
TARGET_USERNAME=${TARGET_USERNAME:-user}
TARGET_HOSTNAME=${TARGET_HOSTNAME:-gentoo}
TARGET_DOMAIN=${TARGET_DOMAIN:-lan}
LOAD_PERCENTAGE=${LOAD_PERCENTAGE:-0.75}
JOBS=${JOBS:-}
TIMEZONE=${TIMEZONE:-UTC}
LOCALE=${LOCALE:-en_US}
L10N=${L10N:-en}
KEYMAP=${KEYMAP:-us}
GENTOO_PROFILE=${GENTOO_PROFILE:-"default/linux/amd64/17.1"}
ZFS_ENABLED=${ZFS_ENABLED:-}
ZFS_RPOOL=${ZFS_RPOOL:-rpool}
ZFS_BPOOL=${ZFS_BPOOL:-}
ROOT_DEV=${ROOT_DEV:-}
GENTOO_MIRRORS=${GENTOO_MIRRORS:-"https://gentoo.osuosl.org/"}
VIDEO_CARDS=${VIDEO_CARDS:-"intel"}
BASE_SYSTEM=${BASE_SYSTEM:-"/root/stage3-*.tar.xz"}
DISTFILES_DIR=${DISTFILES_DIR:-}
TMPFS_ENABLED=${TMPFS_ENABLED:-}
USE=${USE:-"verify-sig rsync-verify"}
ACCEPT_LICENSE=${ACCEPT_LICENSE:-"-* @FREE"}
# shellcheck disable=SC1091
[[ -f "bootstrap.conf" ]] && source ./bootstrap.conf
if [[ -z ${ROOT_DEV[*]} ]]; then
die "required --root-dev argument"
fi
if [[ ${ZFS_ENABLED} ]]; then
require_binary "zpool" "zfs"
if [[ -z $ZFS_RPOOL ]]; then
die "--zfs-rpool argument is not specified"
fi
fi
unpack_base_system() {
log_info "Unpacking Gentoo base system"
(
shopt -s extglob
if [[ ! -f $(ls ${BASE_SYSTEM} 2>/dev/null) ]]; then
die "tarball ${BASE_SYSTEM} does not exist"
fi
cp ${BASE_SYSTEM} ${MNT_PATH} &&
cd ${MNT_PATH} &&
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner &&
rm -f stage3-*.tar.xz
)
}
copy_distfiles() {
if [[ $DISTFILES_DIR ]]; then
log_info "Copying distfiles"
if [[ ! -d "${DISTFILES_DIR}" ]]; then
die "${DISTFILES_DIR} directory does not exist"
fi
cp -r ${DISTFILES_DIR} ${MNT_PATH}/var/cache/distfiles
fi
}
prepare_chroot_env() {
log_info "Preparing chroot environment"
if [[ ! -d "${MNT_PATH}" ]]; then
die "directory ${MNT_PATH} does not exists"
fi
if [[ ! $(findmnt -M "${MNT_PATH}") ]]; then
die "path ${MNT_PATH} is not mounted"
fi
mount --types proc /proc ${MNT_PATH}/proc
mount --rbind /sys ${MNT_PATH}/sys
mount --make-rslave ${MNT_PATH}/sys
mount --rbind /dev ${MNT_PATH}/dev
mount --make-rslave ${MNT_PATH}/dev
test -L /dev/shm && rm /dev/shm && mkdir /dev/shm
mount --types tmpfs --options nosuid,nodev,noexec shm /dev/shm
chmod 1777 /dev/shm
cp --dereference /etc/resolv.conf ${MNT_PATH}/etc/
}
set_locale() {
log_info "Setting locale"
cat <<EOF > "${MNT_PATH}/etc/locale.gen"
C.UTF-8 UTF-8
${LOCALE}.UTF-8 UTF-8
EOF
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
locale-gen
eselect locale set ${LOCALE}.UTF-8
env-update
EOF
}
configure_portage() {
local jobs_param
[[ "$JOBS" -gt 0 ]] && jobs_param=" --jobs=${JOBS}" || jobs_param=""
log_info "Setting up /etc/portage/make.conf"
cat <<EOF > "${MNT_PATH}/etc/portage/make.conf"
# These settings were set by the catalyst build script that automatically
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.
COMMON_FLAGS="-O2 -pipe"
CFLAGS="\${COMMON_FLAGS}"
CXXFLAGS="\${COMMON_FLAGS}"
FCFLAGS="\${COMMON_FLAGS}"
FFLAGS="\${COMMON_FLAGS}"
MAKEOPTS="-j${CPUS}"
ACCEPT_LICENSE="${ACCEPT_LICENSE}"
USE="${USE}"
VIDEO_CARDS="${VIDEO_CARDS}"
FEATURES="candy"
GRUB_PLATFORMS="pc"
GENTOO_MIRRORS="${GENTOO_MIRRORS}"
EMERGE_DEFAULT_OPTS="--keep-going=y --load-average=$(echo "${LOAD_PERCENTAGE} * ${CPUS}" | bc -l)${jobs_param}"
L10N="${L10N}"
# Set portage niceness to minimize potential for updates to cause lag
PORTAGE_NICENESS=19
# NOTE: This stage was built with the bindist Use flag enabled
PORTDIR="/var/db/repos/gentoo"
DISTDIR="/var/cache/distfiles"
PKGDIR="/var/cache/binpkgs"
# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C
EOF
log_info "Setting up portage repository settings"
mkdir --parents ${MNT_PATH}/etc/portage/repos.conf
cp ${MNT_PATH}/usr/share/portage/config/repos.conf ${MNT_PATH}/etc/portage/repos.conf/gentoo.conf
}
sync_repo() {
log_info "Syncing repository"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
emerge-webrsync
eselect profile set ${GENTOO_PROFILE}
EOF
}
install_required_tools() {
log_info "Installing tools required by this script"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
rm -rf /etc/portage/package.use
rm -rf /etc/portage/package.accept_keywords
mkdir -p /etc/portage/package.use
mkdir -p /etc/portage/package.accept_keywords
emerge --noreplace app-portage/flaggie
emerge --noreplace app-eselect/eselect-repository
emerge --noreplace app-shells/gentoo-bashcomp
flaggie media-libs/glfw -wayland
flaggie media-libs/freetype -harfbuzz
emerge --oneshot media-libs/freetype
flaggie media-libs/freetype +harfbuzz
flaggie media-libs/libsdl2 +gles2
flaggie net-libs/zeromq +drafts
flaggie dev-python/QtPy +printsupport
flaggie sys-devel/gcc +objc
flaggie net-libs/nodejs +inspector +npm +snapshot
flaggie dev-lang/mono +minimal
flaggie dev-lang/rust +clippy +rustfmt
flaggie dev-libs/boost +doc
EOF
}
configure_nvidia_pkg() {
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
flaggie x11-drivers/nvidia-drivers +X +abi_x86_32 +dist-kernel +driver +tools +NVIDIA-r2 +\~amd64
flaggie dev-util/nvidia-cuda-toolkit +debugger +nsight +profiler +sanitizer +vis-profiler +NVIDIA-CUDA +\~amd64
flaggie dev-util/nvidia-cuda-sdk +cuda +doc +examples +opencl +CUDPP +\~amd64
flaggie media-video/nvidia_video_sdk +tools +NVIDIA-CODEC-SDK
flaggie media-libs/libglvnd +abi_x86_32
flaggie x11-libs/libX11 +abi_x86_32
flaggie x11-libs/libXext +abi_x86_32
flaggie x11-libs/libxcb +abi_x86_32
flaggie x11-libs/libXau +abi_x86_32
flaggie x11-libs/libXdmcp +abi_x86_32
flaggie x11-base/xcb-proto +abi_x86_32
EOF
}
upgrade_system() {
log_info "Upgrading system"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
emerge --verbose --update --deep --newuse @world
emerge --depclean
EOF
}
set_hostname() {
log_info "Setting hostname"
cat <<EOF > "${MNT_PATH}/etc/conf.d/hostname"
# Set to the hostname of this machine
hostname="${TARGET_HOSTNAME}"
EOF
}
set_domain() {
log_info "Setting domain"
cat <<EOF > "${MNT_PATH}/etc/conf.d/net"
# Set the dns_domain_lo variable to the selected domain name
dns_domain_lo="${TARGET_DOMAIN}"
EOF
}
set_timezone() {
log_info "Setting timezone"
echo "${TIMEZONE}" > ${MNT_PATH}/etc/timezone
rm -f ${MNT_PATH}/etc/localtime
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
emerge --config sys-libs/timezone-data
EOF
}
configure_hosts() {
log_info "Setting up /etc/hosts"
cat <<EOF > "${MNT_PATH}/etc/hosts"
# /etc/hosts: Local Host Database
#
# This file describes a number of aliases-to-address mappings for the for
# local hosts that share this file.
#
# The format of lines in this file is:
#
# IP_ADDRESS canonical_hostname [aliases...]
#
#The fields can be separated by any number of spaces or tabs.
#
# In the presence of the domain name service or NIS, this file may not be
# consulted at all; see /etc/host.conf for the resolution order.
#
# IPv4 and IPv6 localhost aliases
127.0.0.1 ${TARGET_HOSTNAME}.${TARGET_DOMAIN} ${TARGET_HOSTNAME} localhost
::1 ${TARGET_HOSTNAME}.${TARGET_DOMAIN} ${TARGET_HOSTNAME} localhost
#
# Imaginary network.
#10.0.0.2 myname
#10.0.0.3 myfriend
#
# According to RFC 1918, you can use the following IP networks for private
# nets which will never be connected to the Internet:
#
# 10.0.0.0 - 10.255.255.255
# 172.16.0.0 - 172.31.255.255
# 192.168.0.0 - 192.168.255.255
#
# In case you want to be able to connect directly to the Internet (i.e. not
# behind a NAT, ADSL router, etc...), you need real official assigned
# numbers. Do not try to invent your own network numbers but instead get one
# from your network provider (if any) or from your regional registry (ARIN,
# APNIC, LACNIC, RIPE NCC, or AfriNIC.)
#
EOF
}
blacklist_nouveau() {
log_info "Blacklisting nouveau driver"
printf "blacklist nouveau\n" >> ${MNT_PATH}/etc/modprobe.d/blacklist.conf
}
enable_nested_kvm() {
log_info "Enabling nested KVM virtualization"
printf "options kvm_intel nested=1\n" >> ${MNT_PATH}/etc/modprobe.d/kvm_intel.conf
}
enable_tmpfs() {
log_info "Setting up /etc/fstab"
tmpfs_line="tmpfs /tmp tmpfs rw,nodev,nosuid,exec 0 0"
if ! grep -q "${tmpfs_line}" ${MNT_PATH}/etc/fstab; then
printf "%s\n" "${tmpfs_line}" >> ${MNT_PATH}/etc/fstab
fi
}
setup_base_system() {
log_info "Preparing Gentoo base system"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
flaggie sys-kernel/gentoo-kernel-bin +initramfs
emerge --noreplace sys-kernel/gentoo-kernel-bin
emerge --noreplace sys-apps/pciutils
emerge --noreplace sys-kernel/installkernel-gentoo
flaggie sys-kernel/linux-firmware +linux-fw-redistributable +no-source-code
emerge --noreplace sys-kernel/linux-firmware
emerge --noreplace net-misc/netifrc
sed -i 's/^keymap=".*"$/keymap="${KEYMAP}"/g' /etc/conf.d/keymaps
sed -i 's/^clock=".*"$/clock="${HWCLOCK}"/g' /etc/conf.d/hwclock
emerge --noreplace app-admin/sysklogd
rc-update add sysklogd default
emerge --noreplace sys-process/cronie
rc-update add cronie default
crontab /etc/crontab
emerge --noreplace sys-apps/mlocate
flaggie sys-boot/grub +device-mapper +fonts +themes +truetype
emerge --noreplace sys-fs/e2fsprogs
emerge --noreplace sys-fs/xfsprogs
emerge --noreplace sys-fs/reiserfsprogs
emerge --noreplace sys-fs/jfsutils
emerge --noreplace sys-fs/dosfstools
emerge --noreplace sys-fs/btrfs-progs
useradd -m -G users,lp,wheel,audio,cdrom,video -s /bin/bash ${TARGET_USERNAME}
chown -R ${TARGET_USERNAME}:users /home/${TARGET_USERNAME}
emerge --noreplace net-misc/dhcpcd
emerge --noreplace net-wireless/iw
emerge --noreplace net-wireless/wpa_supplicant
emerge --noreplace net-dialup/ppp
emerge --noreplace sys-apps/net-tools
flaggie sys-firmware/intel-microcode +intel-ucode
emerge --noreplace sys-firmware/intel-microcode
emerge --config sys-kernel/gentoo-kernel
emerge --noreplace app-editors/nano
emerge --noreplace app-admin/ansible
EOF
}
install_sudo() {
log_info "Installing sudo"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
flaggie app-admin/sudo +offensive
emerge --changed-use app-admin/sudo
sed -ri 's/^#+\s*(Defaults mail_badpass)$/\1/g' /etc/sudoers
sed -ri 's/^#+\s*(Defaults log_output)$/\1/g' /etc/sudoers
sed -ri 's~^#+\s*(Defaults!/usr/bin/sudoreplay !log_output)$~\1~g' /etc/sudoers
sed -ri 's~^#+\s*(Defaults!/usr/local/bin/sudoreplay !log_output)$~\1~g' /etc/sudoers
sed -ri 's~^#+\s*(Defaults!REBOOT !log_output)$~\1~g' /etc/sudoers
sed -ri 's/^#+\s*(%wheel ALL=\(ALL\) ALL)$/\1/g' /etc/sudoers
EOF
}
configure_zfs() {
log_info "Setting up ZFS on the target system"
mkdir -p ${MNT_PATH}/etc/zfs
cp /etc/zfs/zpool.cache ${MNT_PATH}/etc/zfs/zpool.cache
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
flaggie sys-fs/zfs +rootfs +dist-kernel
flaggie sys-fs/zfs-kmod +rootfs +dist-kernel
flaggie sys-boot/grub +libzfs
emerge --noreplace sys-fs/zfs
rc-update add zfs-import boot
rc-update add zfs-mount boot
rc-update add zfs-share default
rc-update add zfs-zed default
flaggie sys-fs/zfs-auto-snapshot -default-exclude
emerge --noreplace zfs-auto-snapshot
zfs allow ${TARGET_USERNAME} create,mount,mountpoint,snapshot ${ZFS_RPOOL}/home/${TARGET_USERNAME}
chown -R ${TARGET_USERNAME}:users /home/${TARGET_USERNAME}
zgenhostid || true
EOF
}
install_grub() {
log_info "Installing bootloader"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
flaggie media-libs/freetype -harfbuzz
emerge --oneshot media-libs/freetype
flaggie media-libs/freetype +harfbuzz
emerge --noreplace sys-boot/grub:2
EOF
for device in ${ROOT_DEV[*]}; do
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
grub-install ${device}
EOF
done
}
configure_grub() {
log_info "Configuring bootloader"
chroot "${MNT_PATH}" /bin/bash <<EOF
source /etc/profile
grub-mkconfig -o /boot/grub/grub.cfg
EOF
}
clean_after_chroot() {
log_info "Cleaning up after chroot"
for mnt in "proc" "sys" "dev"; do
[[ $(findmnt -M "${MNT_PATH}/${mnt}") ]] && umount -R "${MNT_PATH}/${mnt}"
done
}
unpack_base_system
copy_distfiles
prepare_chroot_env
set_locale
configure_portage
sync_repo
install_required_tools
[[ "${VIDEO_CARDS}" =~ "nvidia" || "${USE}" =~ "cuda" ]] && configure_nvidia_pkg
upgrade_system
set_hostname
set_domain
set_timezone
configure_hosts
blacklist_nouveau
enable_nested_kvm
[[ "${TMPFS_ENABLED}" ]] && enable_tmpfs
setup_base_system
install_sudo
[[ ${ZFS_ENABLED} ]] && configure_zfs
install_grub
configure_grub
[[ ${ZFS_ENABLED} && ${ZFS_BPOOL} ]] && zfs snapshot -r ${ZFS_BPOOL}@install
[[ ${ZFS_ENABLED} ]] && zfs snapshot -r ${ZFS_RPOOL}@install
clean_after_chroot
printf "Done!\n"