Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- [root@917e8160b71e /]# cat /usr/sbin/mkarchiso
- #!/bin/bash
- set -e -u
- export LANG=C
- app_name=${0##*/}
- arch=$(uname -m)
- pkg_list=""
- run_cmd=""
- quiet="y"
- pacman_conf="/etc/pacman.conf"
- export iso_label="ARCH_$(date +%Y%m)"
- iso_publisher="Arch Linux <http://www.archlinux.org>"
- iso_application="Arch Linux Live/Rescue CD"
- install_dir="arch"
- work_dir="work"
- out_dir="out"
- sfs_mode="sfs"
- sfs_comp="xz"
- gpg_key=
- # Show an INFO message
- # $1: message string
- _msg_info() {
- local _msg="${1}"
- echo "[mkarchiso] INFO: ${_msg}"
- }
- # Show an ERROR message then exit with status
- # $1: message string
- # $2: exit code number (with 0 does not exit)
- _msg_error() {
- local _msg="${1}"
- local _error=${2}
- echo
- echo "[mkarchiso] ERROR: ${_msg}"
- echo
- if [[ ${_error} -gt 0 ]]; then
- exit ${_error}
- fi
- }
- _chroot_init() {
- mkdir -p ${work_dir}/airootfs
- _pacman "base syslinux"
- }
- _chroot_run() {
- eval arch-chroot ${work_dir}/airootfs "${run_cmd}"
- }
- _mount_airootfs() {
- trap "_umount_airootfs" EXIT HUP INT TERM
- mkdir -p "${work_dir}/mnt/airootfs"
- _msg_info "Mounting '${work_dir}/airootfs.img' on '${work_dir}/mnt/airootfs'"
- mount "${work_dir}/airootfs.img" "${work_dir}/mnt/airootfs"
- _msg_info "Done!"
- }
- _umount_airootfs() {
- _msg_info "Unmounting '${work_dir}/mnt/airootfs'"
- umount -d "${work_dir}/mnt/airootfs"
- _msg_info "Done!"
- rmdir "${work_dir}/mnt/airootfs"
- trap - EXIT HUP INT TERM
- }
- # Show help usage, with an exit status.
- # $1: exit status number.
- _usage ()
- {
- echo "usage ${app_name} [options] command <command options>"
- echo " general options:"
- echo " -p PACKAGE(S) Package(s) to install, can be used multiple times"
- echo " -r <command> Run <command> inside airootfs"
- echo " -C <file> Config file for pacman."
- echo " Default: '${pacman_conf}'"
- echo " -L <label> Set a label for the disk"
- echo " Default: '${iso_label}'"
- echo " -P <publisher> Set a publisher for the disk"
- echo " Default: '${iso_publisher}'"
- echo " -A <application> Set an application name for the disk"
- echo " Default: '${iso_application}'"
- echo " -D <install_dir> Set an install_dir. All files will by located here."
- echo " Default: '${install_dir}'"
- echo " NOTE: Max 8 characters, use only [a-z0-9]"
- echo " -w <work_dir> Set the working directory"
- echo " Default: '${work_dir}'"
- echo " -o <out_dir> Set the output directory"
- echo " Default: '${out_dir}'"
- echo " -s <sfs_mode> Set SquashFS image mode (img or sfs)"
- echo " img: prepare airootfs.sfs for dm-snapshot usage"
- echo " sfs: prepare airootfs.sfs for overlayfs usage"
- echo " Default: ${sfs_mode}"
- echo " -c <comp_type> Set SquashFS compression type (gzip, lzma, lzo, xz)"
- echo " Default: '${sfs_comp}'"
- echo " -v Enable verbose output"
- echo " -h This message"
- echo " commands:"
- echo " init"
- echo " Make base layout and install base group"
- echo " install"
- echo " Install all specified packages (-p)"
- echo " run"
- echo " run command specified by -r"
- echo " prepare"
- echo " build all images"
- echo " pkglist"
- echo " make a pkglist.txt of packages installed on airootfs"
- echo " iso <image name>"
- echo " build an iso image from the working dir"
- exit ${1}
- }
- # Shows configuration according to command mode.
- # $1: init | install | run | prepare | iso
- _show_config () {
- local _mode="$1"
- echo
- _msg_info "Configuration settings"
- _msg_info " Command: ${command_name}"
- _msg_info " Architecture: ${arch}"
- _msg_info " Working directory: ${work_dir}"
- _msg_info " Installation directory: ${install_dir}"
- case "${_mode}" in
- init)
- _msg_info " Pacman config file: ${pacman_conf}"
- ;;
- install)
- _msg_info " Pacman config file: ${pacman_conf}"
- _msg_info " Packages: ${pkg_list}"
- ;;
- run)
- _msg_info " Run command: ${run_cmd}"
- ;;
- prepare)
- ;;
- pkglist)
- ;;
- iso)
- _msg_info " Image name: ${img_name}"
- _msg_info " Disk label: ${iso_label}"
- _msg_info " Disk publisher: ${iso_publisher}"
- _msg_info " Disk application: ${iso_application}"
- ;;
- esac
- echo
- }
- # Install desired packages to airootfs
- _pacman ()
- {
- _msg_info "Installing packages to '${work_dir}/airootfs/'..."
- if [[ "${quiet}" = "y" ]]; then
- pacstrap -C "${pacman_conf}" -c -G -M "${work_dir}/airootfs" $* &> /dev/null
- else
- pacstrap -C "${pacman_conf}" -c -G -M "${work_dir}/airootfs" $*
- fi
- _msg_info "Packages installed successfully!"
- }
- # Cleanup airootfs
- _cleanup () {
- _msg_info "Cleaning up what we can on airootfs..."
- # Delete initcpio image(s)
- if [[ -d "${work_dir}/airootfs/boot" ]]; then
- find "${work_dir}/airootfs/boot" -type f -name '*.img' -delete
- fi
- # Delete kernel(s)
- if [[ -d "${work_dir}/airootfs/boot" ]]; then
- find "${work_dir}/airootfs/boot" -type f -name 'vmlinuz*' -delete
- fi
- # Delete pacman database sync cache files (*.tar.gz)
- if [[ -d "${work_dir}/airootfs/var/lib/pacman" ]]; then
- find "${work_dir}/airootfs/var/lib/pacman" -maxdepth 1 -type f -delete
- fi
- # Delete pacman database sync cache
- if [[ -d "${work_dir}/airootfs/var/lib/pacman/sync" ]]; then
- find "${work_dir}/airootfs/var/lib/pacman/sync" -delete
- fi
- # Delete pacman package cache
- if [[ -d "${work_dir}/airootfs/var/cache/pacman/pkg" ]]; then
- find "${work_dir}/airootfs/var/cache/pacman/pkg" -type f -delete
- fi
- # Delete all log files, keeps empty dirs.
- if [[ -d "${work_dir}/airootfs/var/log" ]]; then
- find "${work_dir}/airootfs/var/log" -type f -delete
- fi
- # Delete all temporary files and dirs
- if [[ -d "${work_dir}/airootfs/var/tmp" ]]; then
- find "${work_dir}/airootfs/var/tmp" -mindepth 1 -delete
- fi
- # Delete package pacman related files.
- find "${work_dir}" \( -name "*.pacnew" -o -name "*.pacsave" -o -name "*.pacorig" \) -delete
- _msg_info "Done!"
- }
- # Makes a ext4 filesystem inside a SquashFS from a source directory.
- _mkairootfs_img () {
- if [[ ! -e "${work_dir}/airootfs" ]]; then
- _msg_error "The path '${work_dir}/airootfs' does not exist" 1
- fi
- _msg_info "Creating ext4 image of 32GiB..."
- truncate -s 32G "${work_dir}/airootfs.img"
- local _qflag=""
- if [[ ${quiet} == "y" ]]; then
- _qflag="-q"
- fi
- mkfs.ext4 ${_qflag} -O ^has_journal,^resize_inode -E lazy_itable_init=0 -m 0 -F "${work_dir}/airootfs.img"
- tune2fs -c 0 -i 0 "${work_dir}/airootfs.img" &> /dev/null
- _msg_info "Done!"
- _mount_airootfs
- _msg_info "Copying '${work_dir}/airootfs/' to '${work_dir}/mnt/airootfs/'..."
- cp -aT "${work_dir}/airootfs/" "${work_dir}/mnt/airootfs/"
- _msg_info "Done!"
- _umount_airootfs
- mkdir -p "${work_dir}/iso/${install_dir}/${arch}"
- _msg_info "Creating SquashFS image, this may take some time..."
- if [[ "${quiet}" = "y" ]]; then
- mksquashfs "${work_dir}/airootfs.img" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend -comp "${sfs_comp}" -no-progress &> /dev/null
- else
- mksquashfs "${work_dir}/airootfs.img" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend -comp "${sfs_comp}" -no-progress
- fi
- _msg_info "Done!"
- rm ${work_dir}/airootfs.img
- }
- # Makes a SquashFS filesystem from a source directory.
- _mkairootfs_sfs () {
- if [[ ! -e "${work_dir}/airootfs" ]]; then
- _msg_error "The path '${work_dir}/airootfs' does not exist" 1
- fi
- mkdir -p "${work_dir}/iso/${install_dir}/${arch}"
- _msg_info "Creating SquashFS image, this may take some time..."
- if [[ "${quiet}" = "y" ]]; then
- mksquashfs "${work_dir}/airootfs" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend -comp "${sfs_comp}" -no-progress &> /dev/null
- else
- mksquashfs "${work_dir}/airootfs" "${work_dir}/iso/${install_dir}/${arch}/airootfs.sfs" -noappend -comp "${sfs_comp}" -no-progress
- fi
- _msg_info "Done!"
- }
- _mkchecksum () {
- _msg_info "Creating checksum file for self-test..."
- cd "${work_dir}/iso/${install_dir}/${arch}"
- sha512sum airootfs.sfs > airootfs.sha512
- cd ${OLDPWD}
- _msg_info "Done!"
- }
- _mksignature () {
- _msg_info "Creating signature file..."
- cd "${work_dir}/iso/${install_dir}/${arch}"
- gpg --detach-sign --default-key ${gpg_key} airootfs.sfs
- cd ${OLDPWD}
- _msg_info "Done!"
- }
- command_pkglist () {
- _show_config pkglist
- _msg_info "Creating a list of installed packages on live-enviroment..."
- pacman -Q --sysroot "${work_dir}/airootfs" > \
- "${work_dir}/iso/${install_dir}/pkglist.${arch}.txt"
- _msg_info "Done!"
- }
- # Create an ISO9660 filesystem from "iso" directory.
- command_iso () {
- local _iso_efi_boot_args=""
- if [[ ! -f "${work_dir}/iso/isolinux/isolinux.bin" ]]; then
- _msg_error "The file '${work_dir}/iso/isolinux/isolinux.bin' does not exist." 1
- fi
- if [[ ! -f "${work_dir}/iso/isolinux/isohdpfx.bin" ]]; then
- _msg_error "The file '${work_dir}/iso/isolinux/isohdpfx.bin' does not exist." 1
- fi
- # If exists, add an EFI "El Torito" boot image (FAT filesystem) to ISO-9660 image.
- if [[ -f "${work_dir}/iso/EFI/archiso/efiboot.img" ]]; then
- _iso_efi_boot_args="-eltorito-alt-boot
- -e EFI/archiso/efiboot.img
- -no-emul-boot
- -isohybrid-gpt-basdat"
- fi
- _show_config iso
- mkdir -p ${out_dir}
- _msg_info "Creating ISO image..."
- local _qflag=""
- if [[ ${quiet} == "y" ]]; then
- _qflag="-quiet"
- fi
- xorriso -as mkisofs ${_qflag} \
- -iso-level 3 \
- -full-iso9660-filenames \
- -volid "${iso_label}" \
- -appid "${iso_application}" \
- -publisher "${iso_publisher}" \
- -preparer "prepared by mkarchiso" \
- -eltorito-boot isolinux/isolinux.bin \
- -eltorito-catalog isolinux/boot.cat \
- -no-emul-boot -boot-load-size 4 -boot-info-table \
- -isohybrid-mbr ${work_dir}/iso/isolinux/isohdpfx.bin \
- ${_iso_efi_boot_args} \
- -output "${out_dir}/${img_name}" \
- "${work_dir}/iso/"
- _msg_info "Done! | $(ls -sh ${out_dir}/${img_name})"
- }
- # create airootfs.sfs filesystem, and push it in "iso" directory.
- command_prepare () {
- _show_config prepare
- _cleanup
- if [[ ${sfs_mode} == "sfs" ]]; then
- _mkairootfs_sfs
- else
- _mkairootfs_img
- fi
- _mkchecksum
- if [[ ${gpg_key} ]]; then
- _mksignature
- fi
- }
- # Install packages on airootfs.
- # A basic check to avoid double execution/reinstallation is done via hashing package names.
- command_install () {
- if [[ ! -f "${pacman_conf}" ]]; then
- _msg_error "Pacman config file '${pacman_conf}' does not exist" 1
- fi
- #trim spaces
- pkg_list="$(echo ${pkg_list})"
- if [[ -z ${pkg_list} ]]; then
- _msg_error "Packages must be specified" 0
- _usage 1
- fi
- _show_config install
- _pacman "${pkg_list}"
- }
- command_init() {
- _show_config init
- _chroot_init
- }
- command_run() {
- _show_config run
- _chroot_run
- }
- if [[ ${EUID} -ne 0 ]]; then
- _msg_error "This script must be run as root." 1
- fi
- umask 0022
- while getopts 'p:r:C:L:P:A:D:w:o:s:c:g:vh' arg; do
- case "${arg}" in
- p) pkg_list="${pkg_list} ${OPTARG}" ;;
- r) run_cmd="${OPTARG}" ;;
- C) pacman_conf="${OPTARG}" ;;
- L) iso_label="${OPTARG}" ;;
- P) iso_publisher="${OPTARG}" ;;
- A) iso_application="${OPTARG}" ;;
- D) install_dir="${OPTARG}" ;;
- w) work_dir="${OPTARG}" ;;
- o) out_dir="${OPTARG}" ;;
- s) sfs_mode="${OPTARG}" ;;
- c) sfs_comp="${OPTARG}" ;;
- g) gpg_key="${OPTARG}" ;;
- v) quiet="n" ;;
- h|?) _usage 0 ;;
- *)
- _msg_error "Invalid argument '${arg}'" 0
- _usage 1
- ;;
- esac
- done
- shift $((OPTIND - 1))
- if [[ $# -lt 1 ]]; then
- _msg_error "No command specified" 0
- _usage 1
- fi
- command_name="${1}"
- case "${command_name}" in
- init)
- command_init
- ;;
- install)
- command_install
- ;;
- run)
- command_run
- ;;
- prepare)
- command_prepare
- ;;
- pkglist)
- command_pkglist
- ;;
- iso)
- if [[ $# -lt 2 ]]; then
- _msg_error "No image specified" 0
- _usage 1
- fi
- img_name="${2}"
- command_iso
- ;;
- *)
- _msg_error "Invalid command name '${command_name}'" 0
- _usage 1
- ;;
- esac
- # vim:ts=4:sw=4:et:
- [root@917e8160b71e /]#
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement