view sbin/fpkg @ 437:59622f32279d

Add two examples of how to use ftjail and friends to (freebsd-)update a thin jail. 1. Update the thin jail template 2. Update the thin jails These scripts are not yet polished. They are added as used for some times when managing jails.
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 01 May 2024 20:58:54 +0200
parents 84d2735fe7f6
children 9c3b1966ba91
line wrap: on
line source

#!/bin/sh
# -*- indent-tabs-mode: nil; -*-
: 'A pkg frontend for common operations that also operates in all
running jails.

:Author:    Franz Glasner
:Copyright: (c) 2019-2023 Franz Glasner.
            All rights reserved.
:License:   BSD 3-Clause "New" or "Revised" License.
            See LICENSE for details.
            If you cannot find LICENSE see
            <https://opensource.org/licenses/BSD-3-Clause>
:ID:        @(#)@@SIMPLEVERSIONTAG@@

'

VERSION="@@VERSION@@"

USAGE='
USAGE: fpkg [ OPTIONS] COMMAND [ COMMAND-OPTIONS ]

OPTIONS:

  -V    Print the program name and version number to stdout and exit

  -h    Print this help message to stdout and exit

COMMANDS:

  audit

    `pkg audit` on the local host and all running visible and
    compatible jails

  update

    `pkg update` on the local host and all running visible and
    compatible jails

  upgrade

    `pkg upgrade` on the local host and all running visible and
    compatible jails

  check-upgrade
  upgrade-check

    `pkg upgrade -n` on the local host and all running visible and
    compatible jails

  check-fast-track
    Check packages installed from the LocalBSDPorts repository against
    the repositories `FreeBSD` and `LocalBSDPorts` on the local host
    and all visible and compatible jails

  config <name>

    Retrieve the value of a given configuration option on the local host
    and all running visible and compatible jails

  uversion

    Call `freebsd-version -u` on the local host and all running visible
    and compatible jails

  vv

   `pkg -vv` on the local host and all running visible jails

ENVIRONMENT:

  FPKG_AUDIT_FLAGS
                 Additional flags given to `pkg audit`
                 (Default: -Fr)

  FPKG_UPDATE_FLAGS
                 Additional flags given to `pkg update`
                 (Default: empty)

  FPKG_UPGRADE_FLAGS
                 Additional flags given to `pkg upgrade` and `pkg upgrade -n`
                 (Default: empty)

  FPKG_SIGN
                 Marker for the begin of an output group (local host or jail)
                 (Default: "===> ")

  FPKG_SKIPSIGN
                 Marker for the begin of a skipped output group
                 (Default: "----> ")

  All other environment variables that affect `pkg` are effective also.

  A "compatible jail" is a jail that'"'"'s "freebsd-version -u" is the same
  as the host'"'"'s.
'

#
# Configuration directory
#
: ${CONFIGDIR:=@@ETCDIR@@}

test -r "${CONFIGDIR}/pkgtools.conf" && . "${CONFIGDIR}/pkgtools.conf"

: ${FPKG_AUDIT_FLAGS:=-Fr}
: ${FPKG_UPDATE_FLAGS:=}
: ${FPKG_UPGRADE_FLAGS:=}
: ${FPKG_SIGN:='===> '}
: ${FPKG_SKIPSIGN:='----> '}

#
# The official FreeBSD binary repository
#
: ${FREEBSD_REPO:=FreeBSD}

#
# Local repository with ports with default OPTIONS (i.e. unchanged)
# but newer than the packages in the "FreeBSD" repository.
# Some sort of a fast-track repository.
#
: ${LOCALBSDPORTS_REPO:=LocalBSDPorts}


has_same_userland_version() {
    : 'Check whether the jail `_jail` has the same FreeBSD userland version
    as the host the the current process runs.

    Args:
        _jail: the running jail to check for

    Returns:
        0 if the userland versions match, 1 otherwise

    '
    local _jail _host_version _jail_version

    _jail="$1"

    _host_version=$(/bin/freebsd-version -u) || exit 1
    _jail_version=$(jexec -l "${_jail}" /bin/freebsd-version -u) || exit 1
    if [ "${_host_version%%-*}" = "${_jail_version%%-*}" ]; then
        return 0
    fi
    return 1
}


command_uversion() {
    : ' Do a local `freebsd-version -u` and also for all running jails

    '
    echo "LOCALHOST: $(/bin/freebsd-version -u)"
    for _jail in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo "${_jail}: $(jexec -l "${_jail}" /bin/freebsd-version -u)"
    done
}


command_audit() {
    : 'Do a local `pkg audit -Fr` and also for all running jails

    '
    echo "${FPKG_SIGN}LOCALHOST"
    pkg audit ${FPKG_AUDIT_FLAGS}
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            pkg -j "${_j}" audit ${FPKG_AUDIT_FLAGS}
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


command_update() {
    : 'Do a local `pkg update` and also for all running jails

    '
    echo "${FPKG_SIGN}LOCALHOST"
    pkg update ${FPKG_UPDATE_FLAGS}
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            pkg -j "${_j}" update ${FPKG_UPDATE_FLAGS}
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


command_upgrade() {
    : 'Do a local `pkg upgrade` and also for all running jails

    '
    echo "${FPKG_SIGN}LOCALHOST"
    pkg upgrade ${FPKG_UPGRADE_FLAGS}
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            pkg -j "${_j}" upgrade ${FPKG_UPGRADE_FLAGS}
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


command_check_upgrade() {
    : 'Do a local `pkg upgrade -n` and also for all running jails

    '
    echo "${FPKG_SIGN}LOCALHOST"
    pkg upgrade -n ${FPKG_UPGRADE_FLAGS}
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            pkg -j "${_j}" upgrade -n ${FPKG_UPGRADE_FLAGS}
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


command_check_fasttrack() {
    : 'Check the fast-track repository versions against the canonical
    FreeBSD repository versions.

    Input (Globals):
        FREEBSD_REPO:       the (canonical) FreeBSD repository name
        LOCALBSDPORTS_REPO: the fast-track repository name

    '
    local _name local _repo _j

    echo "${FPKG_SIGN}LOCALHOST"
    pkg query '%n %R' |
        while read _name _repo; do
            if [ "${_repo}" = "${LOCALBSDPORTS_REPO}" ]; then
                echo "   ${_name}"
                printf "      %-15s : %s\n" "${LOCALBSDPORTS_REPO}" "$(pkg version -U -r ${LOCALBSDPORTS_REPO} -n ${_name} -v)"
                printf "      %-15s : %s\n" "${FREEBSD_REPO}" "$(pkg version -U -r ${FREEBSD_REPO} -n ${_name} -v)"
            fi
        done
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            pkg -j "${_j}" query '%n %R' |
                while read _name _repo; do
                    if [ "${_repo}" = "${LOCALBSDPORTS_REPO}" ]; then
                        echo "   ${_name}"
                        printf "      %s-15s : %s\n" "${LOCALBSDPORTS_REPO}" "$(pkg -j ${_j} version -U -r ${LOCALBSDPORTS_REPO} -n ${_name} -v)"
                        printf "      %-15s : %s\n" "${FREEBSD_REPO}" "$(pkg -j ${_j} version -U -r ${FREEBSD_REPO} -n ${_name} -v)"
            fi
                done
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


command_config() {
    : 'The `pkg config name` command on the host and all running
    compatible jails

    Args:
        _name: the configuration option to retrieve to

    '
    local _name

    _name="$1"

    if [ -z "${_name}" ]; then
        echo "Usage: fpkg config <name>" >&2
        return 1
    fi
    echo "${FPKG_SIGN}LOCALHOST"
    pkg config "${_name}"
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            # This prints the value on the *host* also
            #pkg -j "${_j}" config "${_name}"
            jexec "${_j}" pkg config "${_name}"
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


command_vv() {
    : 'The `pkg -vv` command on the host and all running compatible jails

    '
    echo "${FPKG_SIGN}LOCALHOST"
    pkg -vv
    for _j in $(jls -N | awk '{if(NR>1)print $1}' | sort); do
        echo ""
        echo "${FPKG_SIGN}JAIL: ${_j}"
        if has_same_userland_version "${_j}"; then
            pkg -j "${_j}" -vv
        else
            echo "${FPKG_SKIPSIGN}SKIPPED because of different userland"
        fi
    done
}


#
# Global option handling
#
while getopts "Vh" _opt ; do
    case ${_opt} in
        V)
            printf 'fpkg %s\n' '@@SIMPLEVERSIONSTR@@'
            exit 0
            ;;
        h)
            echo "${USAGE}"
            exit 0
            ;;
        \?)
            exit 2;
            ;;
        *)
            echo "ERROR: option handling failed" >&2
            exit 2
            ;;
    esac
done

#
# Reset the Shell's option handling system to prepare for handling
# command-local options.
#
shift $((OPTIND-1))
OPTIND=1

command="$1"
shift

test -n "$command" || { echo "ERROR: no command given" >&2; exit 2; }

case "${command}" in
    audit)
        command_audit "$@"
        ;;
    update)
        command_update "$@"
        ;;
    upgrade)
        command_upgrade "$@"
        ;;
    check-upgrade|check_upgrade|upgrade-check|upgrade_check)
        command_check_upgrade "$@"
        ;;
    check-fast-track|check-fasttrack|check_fast_track|check_fasttrack)
        command_check_fasttrack "$@"
        ;;
    config)
        command_config "$@"
        ;;
    uversion)
        command_uversion "$@"
        ;;
    vv)
        command_vv "$@"
        ;;
    *)
        echo "ERROR: unknown command \`${command}'" >&2
        exit 2;
        ;;
esac