FreeBSD-ports-upgrade.sh
Usage examples:
FreeBSD-ports-upgrade.sh sample configuration file (when executed from scripts directory: ./FreeBSD-ports-upgrade/FreeBSD-ports-upgrade.conf or /usr/local/etc/FreeBSD-ports-upgrade/FreeBSD-ports-upgrade.conf or ~/.config/FreeBSD-ports-upgrade/FreeBSD-ports-upgrade.conf):
FreeBSD-ports-upgrade.sh:
Usage examples:
Code:
FreeBSD-ports-upgrade.sh --help
Code:
FreeBSD-ports-upgrade.sh
Code:
FreeBSD-ports-upgrade.sh --jail myjail --jails-root /usr/local/vms --proxy http://user:password@myproxy:3128
FreeBSD-ports-upgrade.sh sample configuration file (when executed from scripts directory: ./FreeBSD-ports-upgrade/FreeBSD-ports-upgrade.conf or /usr/local/etc/FreeBSD-ports-upgrade/FreeBSD-ports-upgrade.conf or ~/.config/FreeBSD-ports-upgrade/FreeBSD-ports-upgrade.conf):
Code:
JailsDir='/your/jails/directory'
Proxy_String='http://your.proxy:3128'
FreeBSD-ports-upgrade.sh:
Code:
#!/bin/sh
#-------------------------------------------------------------------------#
# References
#-------------------------------------------------------------------------#
#
# man sh
# man test
# man sysexits
#
# Handbook Chapter 27.8:Updating FreeBSD with packages
# - https://docs.freebsd.org/en/books/handbook/cutting-edge/
# Handbook Chapter 17.12: Jail Upgrading
# - https://docs.freebsd.org/en/books/handbook/jails/#jail-upgrading
#
# https://stackoverflow.com/questions/592620/how-can-i-check-if-a-program-exists-from-a-bash-script
# - Test if command/programme exists/is installed
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Contributors
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Dependencies
#-------------------------------------------------------------------------#
# Bourne/POSIX shell, or Bourne/POSIX compatible shell
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Known issues
#-------------------------------------------------------------------------#
# Will upgrade FreeBSD-* as well as ports.
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Version history
#-------------------------------------------------------------------------#
version="1.0.0"
# Version 1.0.0:
# - Initial release.
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Signal Traps
#-------------------------------------------------------------------------#
cleanup ( )
{
# cleanup code goes here
# Cannot echo to console from within this function, perhaps to file works.
echo "Cleaning up on exit..."
}
# [Ctrl][c]=SIGINT [Ctrl][\]=SIGQUIT
trap "cleanup" INT QUIT
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Functions
#-------------------------------------------------------------------------#
version ( )
{
printf "%s\nVersion: %s\n" "${scriptNameExt}" "${version}"
exit 0
}
usage-show ( )
{
printf "%s\n" "Usage:"
printf "%s\n" "${scriptNameExt} -v | --version"
printf "%s\n" "${scriptNameExt} -h | --help"
printf "%s\n" "${scriptNameExt} [[-d | --debug] debug_level] [--jail jail] [--jails-root jailsroot] [--proxy proxy]"
printf "%s\n" ''
printf "%s\n" "-v|--version - shows version"
printf "%s\n" "-h|--help - shows usage"
printf "\n"
printf "%s\n" "Where:"
printf "%s\n" "- 'debug_level' is the level of debug logging."
printf "%s\n" "- 'jail' is the name of the jail to upgrade."
printf "%s\n" "- 'jailsroot is the directory containing directories for jails."
printf "%s\n" "- 'proxy_string' is the value to set http_proxy and https_proxy to."
printf "%s\n" " E.g.:"
printf "%s\n" " 'http://proxy:3128' to prompt for proxy credentials"
printf "%s\n" " 'http://user:passwd@proxy:3128' no prompt for proxy credentials"
exit 64 # EX_USAGE (64) The command was used incorrectly, e.g., with the wrong number of arguments, a bad flag, a bad syntax in a parameter, or whatever.
}
command-check ( )
{
# $1 = command to be checked for existence
# $2 = Action: [ (exit) | continue ]
# $3 = Message
# $4 = Exit code
commandCheckAction=${2:-exit}
commandCheckMessage=${3:-${1} not available.}
commandCheckExitCode=${4:-69} # man sysexits: 69 = service unavailable: seems closest
if [ "$( command -v "${1}" > /dev/null 2>&1; echo "$?" )" != '0' ]
then
if ! [ "${commandCheckAction}" = 'continue' ]
then
printf "%s\n" "Error: ${commandCheckMessage}" >&2
exit "${commandCheckExitCode}"
else
printf "%s\n" "Warning: ${commandCheckMessage}"
fi
fi
}
conf_files-process ( )
{
if [ -f "${scriptName}/${scriptName}.conf" ] # Settings in script/product directory - presupposes run from scripts directory
then
. "${scriptName}/${scriptName}.conf"
fi
if [ -f "/usr/local/etc/${scriptName}/${scriptName}.conf" ] # FreeBSD system wide settings
then
. "/usr/local/etc/${scriptName}/${scriptName}.conf"
fi
if [ -f "$HOME/.config/${scriptName}/${scriptName}.conf" ] # User settings
then
. "$HOME/.config/${scriptName}/${scriptName}.conf"
fi
}
cmdline-process ( )
{
# Bibliography
# https://www.grymoire.com/Unix/Sh.html#uh-96
# - Checking for optional arguments
# https://www.grymoire.com/Unix/Sh.html#uh-71
# - $@ versus ${1+$@}
# **!! First incorrect option terminates processing of command line,
# what is left becomes parameters.
while :
do
case "$1" in
'--')
processedTokenCount=$((processedTokenCount + 1));
shift;
break;
;;
-d|--debug)
processedTokenCount=$((processedTokenCount + 1));
shift;
debugLevel="${1}"
;;
-h|--help)
usage-show
;;
-l|--license)
license-cat;
;;
-v|--version)
version
;;
'--jail')
processedTokenCount=$((processedTokenCount + 1));
shift;
Jail_Name="${1}";
;;
'--jails-root')
processedTokenCount=$((processedTokenCount + 1));
shift;
Jails_Root="${1}";
;;
'--proxy')
processedTokenCount=$((processedTokenCount + 1));
shift;
Proxy_String="${1}";
;;
'^-*'|'^--*')
;;
# removing '*)' case will require '--' for "pass through" options/parameters to work
# BUT: not providing the '--' will never exit option parsing - so DO NOT disable '*)' case!
*)
break;
;;
esac
processedTokenCount=$((processedTokenCount + 1));
shift
done
}
proxy-set ()
{
if [ "${Proxy_String#*'@'}" = "${Proxy_String}" ]
then
env-add "http_auth='basic:*'"
fi
env-add "http_proxy=${Proxy_String}"
env-add "https_proxy=""${Proxy_String}"
}
env-add () {
# ${1} = addition to script scope environment
if [ ! "${Env}" ]
then
Env='env'
fi
Env="${Env} ${1}"
}
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# Defaults
#-------------------------------------------------------------------------#
Jail_Name=''
Jails_Root='/usr/local/virtualisation/jails/containers'
Proxy_String=''
rootdir_cmd=''
requiredDependencies='bectl' # list of required programmes (exit script if missing)
optionalDependencies='' # list of optional programmes (continue script if missing)
#-------------------------------------------------------------------------#
#-------------------------------------------------------------------------#
# main
#-------------------------------------------------------------------------#
# Check for optional commands/programmes
if [ -n "${optionalDependencies}" ]
then
for prog in ${optionalDependencies}
do
command-check "${prog}" 'continue'
done
fi
# Check for required commands/programmes
if [ -n "${requiredDependencies}" ]
then
for prog in ${requiredDependencies}
do
command-check "${prog}" 'exit'
done
fi
# script name:
scriptNameExt="${0##*/}"
# script name minus extension:
scriptName="${scriptNameExt%.sh}"
# get script/product default options (stored as global variables)
conf_files-process
# override script/product default configuration with options if specified
processedTokenCount=0
cmdline-process "$@"
shift $((processedTokenCount)) # must remove processed tokens from "$@" outside function
# set proxy URL if specified:
if [ -n "${Proxy_String}" ]
then
proxy-set
fi
if [ -n "${Jail_Name}" ]
then # upgrading jail packages
rootdir_cmd="--rootdir ${Jails_Root}/${Jail_Name}"
# create jail backup:
tmpZFSdataset=$( zfs list | grep "${Jails_Root}$" | awk '{print $1}' )
zfs snapshot -r "${tmpZFSdataset}/${Jail_Name}@ports-upgrade-$( uname -r ).$( date '+%FT%H%M%S%Z' )"
if [ "$?" -ne "0" ]
then
printf "%s\n" "Error creating backup snapshot."
printf "%s\n" "It is recommended a suitable snapshot be created manually before proceeding."
read -p "Do you wish to continue now? [y/N]" -r continue
if ! [ "${continue}" = "y" -o "${continue}" = "Y" ]
then
exit 73 # EX_CANTCREAT (73)
fi
fi
else # upgrading host packages
# create boot environment backup
bectl create -r "ports-upgrade-$( uname -r ).$( date '+%FT%H%M%S%Z' )"
if [ "$?" -ne "0" ]
then
printf "%s\n" "Error creating backup boot environment."
printf "%s\n" "It is recommended a boot environment be created manually before proceeding."
read -p "Do you wish to continue now? [y/N]" -r continue
if ! [ "${continue}" = "y" -o "${continue}" = "Y" ]
then
exit 73 # EX_CANTCREAT (73)
fi
fi
fi
# upgrade all ports including FreeBSD-* ports ("base" operating system):
${Env} pkg ${rootdir_cmd} upgrade
# Check for Failed Configuration Updates:
find /etc /usr/local/etc -name '*.pkgnew' -ls
printf "\n"
# reboot
if [ -n "${Jail_Name}" ]
then
printf "%s" "Ports upgrade complete. Do you wish to restart jail ${Jail_Name} now? [y/N]: "
else
printf "%s" "Ports upgrade complete. Do you wish to reboot now? [y/N]: "
fi
read -r continue
if [ "${continue}" = "y" -o "${continue}" = "Y" ]
then
if [ -n "${Jail_Name}" ]
then
service jail restart "${Jail_Name}"
else
shutdown -r now 'Rebooting after upgrading.'
fi
fi
printf "\n"
exit 0
#-------------------------------------------------------------------------