#!/bin/bash # Purpose {{{ # This script will download some diagnostic tools. # 1. Memtest # 2. Gparted # and make a sample menu.cfg config file. # }}} # Vars {{{ readonly PROGNAME=$(basename "${0}") readonly NBARGS="${#}" [ -z "${DEBUG}" ] && DEBUG=1 ## Export DEBUG for sub-script export DEBUG # Default value for TFTP's directory if command -v in.tftpd > /dev/null; then source /etc/default/tftpd-hpa else TFTP_DIRECTORY="/srv/tftp" fi # Tools versions MEMTEST_VERSION_DEFAULT="$(curl --no-progress-meter http://memtest.org/ \ | sed --silent 's;.*VERSION : \([[:alnum:]]*.[[:alnum:]]*\).*.*;\1;p')" GPARTED_VERSION_DEFAULT="$(curl --no-progress-meter https://gparted.org/ \ | sed --silent 's;.*Live \(.*\).*;\1;p')" # TFTP tree DIAG_INSTALLER_DIR="${TFTP_DIRECTORY}/installer" CONFIG_PXE="${DIAG_INSTALLER_DIR}/menu.cfg.diag.example" MEMTEST_INSTALLER_DIR="${DIAG_INSTALLER_DIR}/memtest" GPARTED_INSTALLER_DIR="${DIAG_INSTALLER_DIR}/gparted" ## Colors readonly PURPLE='\033[1;35m' readonly RED='\033[0;31m' readonly RESET='\033[0m' readonly COLOR_DEBUG="${PURPLE}" # }}} usage() { # {{{ cat <<- EOF usage: $PROGNAME [-d|-h|-m] This script will download some diagnostic tools (eg. Memtest, Gparted,…). EXAMPLES : - Download default diagnostic tools. ${PROGNAME} - Download a specific version of Gparted (default : ${GPARTED_VERSION_DEFAULT}). ${PROGNAME} --gparted "1.0.0-5" - Download a specific version of Memtest (default : ${MEMTEST_VERSION_DEFAULT}). ${PROGNAME} --memtest "3.01" OPTIONS : -g,--gparted Set the version of Gparted to download. -m,--memtest Set the version of Memtest to download. -d,--debug Enable debug messages. -h,--help Print this help message. EOF } # }}} debug_message() { # {{{ local_message="${1}" ## Print message if DEBUG is enable (=0) [ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG − ${PROGNAME} : ${local_message}" return 0 } # }}} error_message() { # {{{ local_error_message="${1}" local_error_code="${2}" ## Print message printf '%b\n' "ERROR − ${PROGNAME} : ${RED}${local_error_message}${RESET}" exit "${local_error_code:=66}" } # }}} define_vars() { # {{{ # If memtest_version wasn't defined (argument) {{{ if [ -z "${memtest_version}" ]; then ## Use default value memtest_version="${MEMTEST_VERSION_DEFAULT}" fi # }}} # If gparted_version wasn't defined (argument) {{{ if [ -z "${gparted_version}" ]; then ## Use default value gparted_version="${GPARTED_VERSION_DEFAULT}" fi # }}} } # }}} is_var_empty() { # {{{ ## Return False by default return_var_empty="1" ## Total number of variables to test local_total_var="${#}" loop_count_var_empty="0" ## While it remains a variable to test while [ "${local_total_var}" -gt "${loop_count_var_empty}" ]; do debug_message "is_var_empty − \ Test var: ${1}." ### Test if this is empty and set return value to True [ -z "${1}" ] && return_var_empty="0" ### Increase the number of tested variables loop_count_var_empty=$((loop_count_var_empty+1)) ### Shift to the next variable shift done return "${return_var_empty}" } # }}} is_file_absent() { # {{{ local_file_absent="${1}" ## File exists by default return_is_file_absent="1" ### Check if the file exists # shellcheck disable=SC2086 if find ${local_file_absent} > /dev/null 2>&1; then return_is_file_absent="1" debug_message "is_file_absent − \ The file ${RED}${local_file_absent}${COLOR_DEBUG} exists." else return_is_file_absent="0" debug_message "is_file_absent − \ The file ${RED}${local_file_absent}${COLOR_DEBUG} doesn't exist." fi return "${return_is_file_absent}" } # }}} download_file() { # {{{ local_url="${1}" local_dest_file="${2}" debug_message "download_file − \ Download ${local_url} to ${RED}${local_dest_file}${COLOR_DEBUG} ." wget --quiet "${local_url}" --output-document="${local_dest_file}" ## Unset variables unset local_url unset local_dest_file } # }}} is_file_empty() { # {{{ local_file="${1}" ## File is empty by default return_is_file_empty="0" ### Check if the file is empty if [ ! -s "${local_file}" ]; then return_is_file_empty="0" debug_message "is_file_empty − \ The file ${RED}${local_file}${COLOR_DEBUG} is empty or doesn't exists." else return_is_file_empty="1" debug_message "is_file_empty − \ The file ${RED}${local_file}${COLOR_DEBUG} exists and has a size greater than zero." fi ## Unset variables unset local_file return "${return_is_file_empty}" } # }}} main() { # {{{ # Define all vars define_vars # If memtest_version is empty {{{ # Exit with error is_var_empty "${memtest_version}" \ && error_message "Memtest version variable is empty" 6 # }}} # If gparted_version is empty {{{ # Exit with error is_var_empty "${gparted_version}" \ && error_message "Gparted version variable is empty" 6 # }}} # Create diagnostic tools directory and config file mkdir --parents -- "${DIAG_INSTALLER_DIR}" \ || error_message "Can't create ${DIAG_INSTALLER_DIR}/ directory." 1 true > ${CONFIG_PXE} # Memtest {{{ MEMTEST_URL="http://www.memtest.org/download/${memtest_version}/memtest86+-${memtest_version}.bin.gz" MEMTEST_BIN="memtest86+-${memtest_version}.bin" # If this version is not already present on the system if is_file_absent "${MEMTEST_INSTALLER_DIR}/${memtest_version}"; then ## (re)Create the installer directory rm --recursive --force -- "${MEMTEST_INSTALLER_DIR}" mkdir --parents -- "${MEMTEST_INSTALLER_DIR}" pushd "${MEMTEST_INSTALLER_DIR}" > /dev/null \ || error_message "Can't move to ${MEMTEST_INSTALLER_DIR} directory." 2 ## Download and extract the last version wget --quiet "${MEMTEST_URL}" -O - | gzip --decompress > "${MEMTEST_BIN}" is_file_empty "${MEMTEST_BIN}" \ && error_message "${MEMTEST_BIN} is empty." 3 ## Set simpler name (without the **.bin** extension !) ln --symbolic -- "${MEMTEST_BIN}" memtest86+ ### Add flag file to know that this version is available true > "${MEMTEST_INSTALLER_DIR}/${memtest_version}" popd > /dev/null \ || error_message "Can't move back from ${MEMTEST_INSTALLER_DIR}/ directory." 2 fi # Config file /bin/cat >> "${CONFIG_PXE}" << EOF label memtest menu label ^Memory diagnostic tool (Memtest) kernel installer/memtest/memtest86+ EOF # }}} # Gparted {{{ # For available classic architecture for ARCH in amd64 i686; do GPARTED_URL="http://downloads.sourceforge.net/project/gparted/gparted-live-stable/${gparted_version}/gparted-live-${gparted_version}-${ARCH}.zip" GPARTED_TEMP_FILE="gparted-live-${gparted_version}-${ARCH}.zip" # If this version is not already present on the system if is_file_absent "${GPARTED_INSTALLER_DIR}/${ARCH}/${gparted_version}"; then ## (re)Create the installer directory for this architecture rm --recursive --force -- "${GPARTED_INSTALLER_DIR}/${ARCH}" mkdir --parents -- "${GPARTED_INSTALLER_DIR}/${ARCH}" pushd "${GPARTED_INSTALLER_DIR}/${ARCH}" > /dev/null \ || error_message "Can't move to ${GPARTED_INSTALLER_DIR}/${ARCH} directory." 2 ## Download and extract the last version download_file "${GPARTED_URL}" "${GPARTED_TEMP_FILE}" is_file_empty "${GPARTED_TEMP_FILE}" \ && error_message "${GPARTED_TEMP_FILE} is empty." 3 unzip -qq -j "${GPARTED_TEMP_FILE}" live/filesystem.squashfs live/initrd.img live/vmlinuz -d . \ || error_message "Can't properly extract ${GPARTED_TEMP_FILE} archive." rm --force -- "${GPARTED_TEMP_FILE}" ### Add flag file to know that this version is available true > "${GPARTED_INSTALLER_DIR}/${ARCH}/${gparted_version}" /bin/cat >> "${CONFIG_PXE}" << EOF label gpartedlive${ARCH} menu label Partiton Manager ${ARCH} (^Gparted) kernel installer/gparted/${ARCH}/vmlinuz append initrd=installer/gparted/${ARCH}/initrd.img boot=live config components union=overlay username=user noswap noeject ip= vga=788 fetch=tftp://129.20.203.27/installer/gparted/${ARCH}/filesystem.squashfs EOF popd > /dev/null \ || error_message "Can't move back from ${GPARTED_INSTALLER_DIR}/${ARCH}/ directory." 2 fi done ### }}} # Config file /bin/cat >> "${CONFIG_PXE}" << EOF label separator menu label ----- label mainmenu menu label ^Back.. menu exit EOF } # }}} # Manage arguments # {{{ # This code can't be in a function due to argument management if [ ! "${NBARGS}" -eq "0" ]; then manage_arg="0" ## If the first argument is not an option if ! printf -- '%s' "${1}" | grep -q -E -- "^-+"; then ## Print help message and exit printf '%b\n' "${RED}Invalid option: ${1}${RESET}" printf '%b\n' "---" usage exit 1 fi # Parse all options (start with a "-") one by one while printf -- '%s' "${1}" | grep -q -E -- "^-+"; do case "${1}" in -g|--gparted ) ## Define gparted_version ## Move to the next argument shift ## Define var readonly gparted_version="${1}" ;; -m|--memtest ) ## Define memtest_version ## Move to the next argument shift ## Define var readonly memtest_version="${1}" ;; -d|--debug ) ## debug DEBUG=0 ;; -h|--help ) ## help usage ## Exit after help informations exit 0 ;; * ) ## unknow option printf '%b\n' "${RED}Invalid option: ${1}${RESET}" printf '%b\n' "---" usage exit 1 ;; esac debug_message "Arguments management − \ ${RED}${1}${COLOR_DEBUG} option managed." ## Move to the next argument shift manage_arg=$((manage_arg+1)) done debug_message "Arguments management − \ ${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed." else debug_message "Arguments management − \ No arguments/options to manage." fi # }}} main exit 0