You've already forked Proxmox-LXC-Tool
363 lines
14 KiB
Bash
363 lines
14 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
|
|
###
|
|
#
|
|
# Options Section
|
|
#
|
|
###
|
|
|
|
set -e
|
|
set -u
|
|
set -o pipefail
|
|
|
|
|
|
###
|
|
#
|
|
# Function Section
|
|
#
|
|
###
|
|
|
|
function ct_check () {
|
|
message 'Check container consistency'
|
|
/usr/bin/test -d "${CT_REALPATH}" || \
|
|
error '\r\rCheck container consistency \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The selected folder can not be found.\n'
|
|
message '\r\rCheck container consistency \xE2\x9C\x94\n'
|
|
}
|
|
|
|
function error () {
|
|
if [ -n "${1:-}" ]; then
|
|
/usr/bin/echo -n -e "${1}"
|
|
fi
|
|
if [ -n "${2:-}" ]; then
|
|
/usr/bin/echo -n -e "${2}"
|
|
fi
|
|
exit 1
|
|
}
|
|
|
|
function help () {
|
|
local HELP
|
|
case "${1}" in
|
|
command)
|
|
read -r -d '' HELP << EOL
|
|
Usage: pve-lxc (OPTION) (CONTAINER)
|
|
|
|
Options:
|
|
[ -a ] [ CONTAINER ] | Archive Container
|
|
[ -c ] [ CONTAINER ] | Chroot Container
|
|
[ -h ] | Help
|
|
[ -p ] [ CONTAINER ] | Prepare Container
|
|
[ -r ] [ CONTAINER ] | Container Repository
|
|
EOL
|
|
;;
|
|
archive)
|
|
read -r -d '' HELP << EOL
|
|
Usage: pve-lxc -a (CONTAINER)
|
|
|
|
Description:
|
|
Compresses the container with
|
|
the data compression format
|
|
'xz' and generates a hash sum
|
|
of it.
|
|
EOL
|
|
;;
|
|
chroot)
|
|
read -r -d '' HELP << EOL
|
|
Usage: pve-lxc -c (CONTAINER)
|
|
|
|
Description:
|
|
Change the root environment
|
|
into the container.
|
|
EOL
|
|
;;
|
|
prepare)
|
|
read -r -d '' HELP << EOL
|
|
Usage: pve-lxc -p (CONTAINER)
|
|
|
|
Description:
|
|
Prepare and/or clean up the
|
|
container.
|
|
EOL
|
|
;;
|
|
repository)
|
|
read -r -d '' HELP << EOL
|
|
Usage: pve-lxc -r (CONTAINER)
|
|
|
|
Description:
|
|
Download one of the following
|
|
images from the repository.
|
|
|
|
- Debian GNU/Linux [ARM64]
|
|
- arm64_debian_bookworm
|
|
- Ubuntu GNU/Linux [ARM64]
|
|
- arm64_ubuntu_noble-numbat
|
|
EOL
|
|
;;
|
|
esac
|
|
/usr/bin/echo -e "${HELP}"
|
|
}
|
|
|
|
function message () {
|
|
if [ -n "${1:-}" ]; then
|
|
/usr/bin/echo -n -e "${1}"
|
|
fi
|
|
}
|
|
|
|
|
|
###
|
|
#
|
|
# Runtime Environment
|
|
#
|
|
###
|
|
|
|
/usr/bin/echo -e 'Proxmox Virtual Environment Container Tool\n'
|
|
|
|
if [[ "${EUID}" -ne '0' ]]; then
|
|
/usr/bin/echo -e 'Error: Permission Denied'
|
|
exit 1
|
|
fi
|
|
|
|
while getopts ':a:c:hp:r:' OPT; do
|
|
case "${OPT}" in
|
|
a)
|
|
CT_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
CT_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
CT_DIRNAME=$(/usr/bin/dirname "${CT_REALPATH}")
|
|
ct_check
|
|
message 'Compress container'
|
|
/usr/bin/tar --create --use-compress-program="/usr/bin/xz -9 --extreme" --file "${CT_DIRNAME}/${CT_BASENAME}.tar.xz" --directory="${CT_REALPATH}" '.' || \
|
|
error '\r\rGenerate container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container path can not be compressed.\n'
|
|
message '\r\rGenerate container \xE2\x9C\x94\n'
|
|
message 'Generate hash'
|
|
/usr/bin/sha512sum "${CT_DIRNAME}/${CT_BASENAME}.tar.xz" | /usr/bin/sed --expression='s, .*/, ,' >> "${CT_DIRNAME}/${CT_BASENAME}.tar.xz.sha512sum" || \
|
|
error '\r\rGenerate hash \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container hash can not be generated.\n'
|
|
message '\r\rGenerate hash \xE2\x9C\x94\n'
|
|
exit 0
|
|
;;
|
|
c)
|
|
CT_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
CT_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
ct_check
|
|
message "Bind filesystem '/dev'"
|
|
if ! /usr/bin/grep --quiet "${CT_REALPATH}/dev" '/proc/mounts'; then
|
|
/usr/bin/mount --bind '/dev' --target "${CT_REALPATH}/dev" &> '/dev/null' || \
|
|
error "\r\rBind filesystem '/dev' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be binded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/dev' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/dev/pts'"
|
|
if ! /usr/bin/grep --quiet "${CT_REALPATH}/dev/pts" '/proc/mounts'; then
|
|
/usr/bin/mount --bind '/dev/pts' --target "${CT_REALPATH}/dev/pts" &> '/dev/null' || \
|
|
error "\r\rBind filesystem '/dev/pts' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be binded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/dev/pts' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/dev/mqueue'"
|
|
if ! /usr/bin/grep --quiet "${CT_REALPATH}/dev/mqueue" '/proc/mounts'; then
|
|
/usr/bin/mount --bind '/dev/mqueue' --target "${CT_REALPATH}/dev/mqueue" &> '/dev/null' || \
|
|
error "\r\rBind filesystem '/dev/mqueue' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be bounded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/dev/mqueue' \xE2\x9C\x94\n"
|
|
message "Slave filesystem '/dev'"
|
|
if ! /usr/bin/grep --quiet "${CT_REALPATH}/dev" '/proc/mounts'; then
|
|
/usr/bin/mount --make-rslave --target "${CT_REALPATH}/dev" &> '/dev/null' || \
|
|
error "\r\rSlave filesystem '/dev' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be slaved.\n'
|
|
fi
|
|
message "\r\rSlave filesystem '/dev' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/proc'"
|
|
if ! /usr/bin/grep --quiet "${CT_REALPATH}/proc" '/proc/mounts'; then
|
|
/usr/bin/mount --types 'proc' --source '/proc' --target "${CT_REALPATH}/proc" &> '/dev/null' || \
|
|
error "\r\rBind filesystem '/proc' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be bounded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/proc' \xE2\x9C\x94\n"
|
|
message "Bind filesystem '/sys'"
|
|
if ! /usr/bin/grep --quiet "${CT_REALPATH}/sys" '/proc/mounts'; then
|
|
/usr/bin/mount --types 'sysfs' --source '/sys' --target "${CT_REALPATH}/sys" &> '/dev/null' || \
|
|
error "\r\rBind filesystem '/sys' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be bounded.\n'
|
|
fi
|
|
message "\r\rBind filesystem '/sys' \xE2\x9C\x94\n"
|
|
|
|
message 'Prepare System-Resolver'
|
|
RESOLVCONF='0'
|
|
if [[ -L "${CT_REALPATH}/etc/resolv.conf" ]]; then
|
|
RESOLVCONF='1'
|
|
/usr/bin/unlink "${CT_REALPATH}/etc/resolv.conf" || \
|
|
error '\r\rPrepare System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be unlinked.\n'
|
|
fi
|
|
/usr/bin/cp --force '/etc/resolv.conf' "${CT_REALPATH}/etc/resolv.conf" || \
|
|
error '\r\rPrepare System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be copied.\n'
|
|
message '\r\rPrepare System-Resolver \xE2\x9C\x94\n'
|
|
|
|
message '\n ... exit chroot environment ... \n\n'
|
|
/usr/bin/sleep '3s'
|
|
/usr/sbin/chroot "${CT_REALPATH}" || true
|
|
message '\n ... exit chroot environment ... \n\n'
|
|
/usr/bin/sleep '3s'
|
|
|
|
message 'Reset System-Resolver'
|
|
/usr/bin/rm --force "${CT_REALPATH}/etc/resolv.conf" || \
|
|
error '\r\rReset System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be removed.\n'
|
|
if [[ "${RESOLVCONF}" == '1' ]]; then
|
|
/usr/bin/ln --force --symbolic '../run/systemd/resolve/stub-resolv.conf' "${CT_REALPATH}/etc/resolv.conf" || \
|
|
error '\r\rReset System-Resolver \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The resolv.conf can not be linked.\n'
|
|
fi
|
|
unset RESOLVCONF
|
|
message '\r\rReset System-Resolver \xE2\x9C\x94\n'
|
|
|
|
message "Unbind filesystem '/dev'"
|
|
if /usr/bin/grep --quiet "${CT_REALPATH}/dev" '/proc/mounts'; then
|
|
/usr/bin/umount --recursive "${CT_REALPATH}/dev" || \
|
|
error "\r\rUnbind filesystem '/dev' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be unbound.\n'
|
|
fi
|
|
message "\r\rUnbind filesystem '/dev' \xE2\x9C\x94\n"
|
|
message "Unbind filesystem '/proc'"
|
|
if /usr/bin/grep --quiet "${CT_REALPATH}/proc" '/proc/mounts'; then
|
|
/usr/bin/umount --recursive "${CT_REALPATH}/proc" || \
|
|
error "\r\rUnbind filesystem '/proc' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be unbound.\n'
|
|
fi
|
|
message "\r\rUnbind filesystem '/proc' \xE2\x9C\x94\n"
|
|
message "Unbind filesystem '/sys'"
|
|
if /usr/bin/grep --quiet "${CT_REALPATH}/sys" '/proc/mounts'; then
|
|
/usr/bin/umount --recursive "${CT_REALPATH}/sys" || \
|
|
error "\r\rUnbind filesystem '/sys' \xE2\x9D\x8C\n" \
|
|
' \xE2\x86\x92 Error: The filesystem can not be unbound.\n'
|
|
fi
|
|
message "\r\rUnbind filesystem '/sys' \xE2\x9C\x94\n"
|
|
exit 0
|
|
;;
|
|
h)
|
|
set +e
|
|
help 'command'
|
|
exit 0
|
|
;;
|
|
p)
|
|
CT_BASENAME=$(/usr/bin/basename "${OPTARG}")
|
|
CT_REALPATH=$(/usr/bin/realpath "${OPTARG}")
|
|
CT_DIRNAME=$(/usr/bin/dirname "${CT_REALPATH}")
|
|
ct_check
|
|
message 'Open filelist'
|
|
if [ -f "/usr/lib/pve-lxc/${CT_BASENAME}.txt" ]; then
|
|
/usr/bin/cp --update='none' "/usr/lib/pve-lxc/${CT_BASENAME}.txt" "${CT_DIRNAME}/${CT_BASENAME}.txt" || \
|
|
error '\r\rOpen filelist \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filelist can not be copied.\n'
|
|
elif [[ ! -f "/usr/lib/pve-lxc/${CT_BASENAME}.txt" ]]; then
|
|
/usr/bin/cp --update='none' "/usr/lib/pve-lxc/default.txt" "${CT_DIRNAME}/${CT_BASENAME}.txt" || \
|
|
error '\r\rOpen filelist \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filelist can not be copied.\n'
|
|
fi
|
|
/usr/bin/nano "${CT_DIRNAME}/${CT_BASENAME}.txt" || \
|
|
error '\r\rOpen filelist \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The filelist can not be opened.\n'
|
|
message '\r\rOpen filelist \xE2\x9C\x94\n'
|
|
message 'Remove files'
|
|
mapfile -t CLEANUP_LIST < <(/usr/bin/cat "${CT_DIRNAME}/${CT_BASENAME}.txt" | /usr/bin/sed '/#.*/d' | while read -r CLEANUP_PATH; do /usr/bin/echo "${CT_REALPATH}${CLEANUP_PATH}"; done)
|
|
for CLEANUP_LIST in "${CLEANUP_LIST[@]}"; do
|
|
/usr/bin/sh -c "/usr/bin/ls --directory ${CLEANUP_LIST} | /usr/bin/xargs /usr/bin/rm --force --recursive" &> '/dev/null' || \
|
|
error '\r\rRemove files \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The file or directory >${CLEANUP_LIST}< can not be removed.\n"
|
|
done
|
|
unset CLEANUP_LIST
|
|
message '\r\rRemove files \xE2\x9C\x94\n'
|
|
message 'Create configuration'
|
|
/usr/bin/test -f "${CT_REALPATH}/etc/hostname" && \
|
|
/usr/bin/cp --force '/usr/lib/pve-lxc/hostname' "${CT_REALPATH}/etc/hostname"
|
|
/usr/bin/test -f "${CT_REALPATH}/etc/hosts" && \
|
|
/usr/bin/cp --force '/usr/lib/pve-lxc/hosts' "${CT_REALPATH}/etc/hosts"
|
|
/usr/bin/test -f "${CT_REALPATH}/etc/network/interfaces" && \
|
|
/usr/bin/cp --force '/usr/lib/pve-lxc/interfaces' "${CT_REALPATH}/etc/network/interfaces"
|
|
/usr/bin/test -f "${CT_REALPATH}/etc/resolv.conf" && \
|
|
/usr/bin/cp --force '/usr/lib/pve-lxc/resolv.conf' "${CT_REALPATH}/etc/resolv.conf"
|
|
message '\r\rCreate configuration \xE2\x9C\x94\n'
|
|
message 'Clear logfiles'
|
|
mapfile -t CLEANUP_LIST < <(/usr/bin/find "${CT_REALPATH}/var/log" -type 'f')
|
|
for CLEANUP_LIST in "${CLEANUP_LIST[@]}"; do
|
|
/usr/bin/dd if=/dev/null of="${CLEANUP_LIST}" &> '/dev/null' || \
|
|
error '\r\rClear logfiles \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The file >${CLEANUP_LIST}< can not be cleared.\n"
|
|
done
|
|
unset CLEANUP_LIST
|
|
mapfile -t CLEANUP_LIST < <(/usr/bin/find "${CT_REALPATH}/var/logrotate" -type 'f')
|
|
for CLEANUP_LIST in "${CLEANUP_LIST[@]}"; do
|
|
/usr/bin/sh -c "/usr/bin/ls --directory ${CLEANUP_LIST} | /usr/bin/xargs /usr/bin/rm --force --recursive" &> '/dev/null' || \
|
|
error '\r\rClear logfiles \xE2\x9D\x8C\n' \
|
|
" \xE2\x86\x92 Error: The file >${CLEANUP_LIST}< can not be removed.\n"
|
|
done
|
|
message '\r\rClear logfiles \xE2\x9C\x94\n'
|
|
exit 0
|
|
;;
|
|
r)
|
|
message 'Download container'
|
|
if [[ -d "./${OPTARG}" ]]; then
|
|
error '\r\rDownload container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container already exists.\n'
|
|
fi
|
|
/usr/bin/wget --quiet --output-document="./${OPTARG}.tar.xz" --no-hsts "https://repository.privlab.it/pve-lxc/${OPTARG}.tar.xz" &> '/dev/null' || \
|
|
error '\r\rDownload container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container can not be downloaded.\n'
|
|
/usr/bin/wget --quiet --output-document="./${OPTARG}.tar.xz.sha512sum" --no-hsts "https://repository.privlab.it/pve-lxc/${OPTARG}.tar.xz.sha512sum" &> '/dev/null' || \
|
|
error '\r\rDownload container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container SHA512SUM can not be downloaded.\n'
|
|
message '\r\rDownload container \xE2\x9C\x94\n'
|
|
message 'Compare hash'
|
|
/usr/bin/sha512sum --check --strict "./${OPTARG}.tar.xz.sha512sum" &> '/dev/null' || \
|
|
error '\r\rCompare hash \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The hash can not be verified.\n'
|
|
/usr/bin/rm --force "./${OPTARG}.tar.xz.sha512sum" || \
|
|
error '\r\rCompare hash \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The hash can not be removed.\n'
|
|
message '\r\rCompare hash \xE2\x9C\x94\n'
|
|
message 'Decompress container'
|
|
/usr/bin/install --directory "./${OPTARG}" || \
|
|
error '\r\rDecompress container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container path can not be installed.\n'
|
|
/usr/bin/tar --extract --file="./${OPTARG}.tar.xz" --directory="./${OPTARG}" || \
|
|
error '\r\rDecompress container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The container can not be decompressed.\n'
|
|
/usr/bin/rm --force "./${OPTARG}.tar.xz" || \
|
|
error '\r\rDecompress container \xE2\x9D\x8C\n' \
|
|
' \xE2\x86\x92 Error: The compressed container can not be removed.\n'
|
|
message '\r\rDecompress container \xE2\x9C\x94\n'
|
|
exit 0
|
|
;;
|
|
-*|*)
|
|
set +e
|
|
case "${1}" in
|
|
-a)
|
|
help 'archive'
|
|
exit 0
|
|
;;
|
|
-c)
|
|
help 'chroot'
|
|
exit 0
|
|
;;
|
|
-p)
|
|
help 'prepare'
|
|
exit 0
|
|
;;
|
|
-r)
|
|
help 'repository'
|
|
exit 0
|
|
;;
|
|
esac
|
|
help 'command'
|
|
exit 0
|
|
;;
|
|
esac
|
|
done
|
|
set +e
|
|
help 'command'
|
|
shift $((OPTIND-1))
|