directadmin-scripts/da_php_version_selections.sh

244 lines
11 KiB
Bash
Executable File

#!/bin/bash
# A script to save and restore selection of actual PHP version for each domain.
#
# Repository: https://gitlab.com/nordhost/da-scripts
# Copyright (C) 2021 Kristian Rønningen
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Usage:
# php-version-selections <selections_file>
#
# Ran without arguments, the script will print the current PHP selection for
# each domain. This output can be redirected to a file ("selections_file") to be
# used as input to the script later.
#
# Ran with a filename as the only argument, the script will try to ensure the
# desired version of PHP is selected for the domain, regardless of the order of
# the versions in options.conf. This can be useful if you want to for example
# change the current default version, but want to let domains still use the same
# version, even if they were just using the default one. It will also allow you
# to reorder the PHP versions in options.conf if you want to, and still let
# domains use the same PHP version afterwards.
#
# If a domain has selected to use a PHP version that no longer exist among the
# four available versions, it will fall back to use the default version,
# whatever it may be.
#
# A typical use case/scenario would be:
#
# 1) You save the current PHP selections,
# `php-version-selections > ~/selections.txt`
# 2) You update options.conf and rearrange PHP versions, or change the default
# 3) You update selections to make sure domains get the correct PHP version,
# `php-versions-selections selections.txt`
# 4) You run `/usr/local/directadmin/custombuild/build rewrite_confs`
#
# NOTE:
# * Error detection might not be present in all steps. Use at your own risk.
# * Domains that are domain pointers will not have their own config file, and
# will therefore return "wrerror"
#
if [ ! -r "/etc/virtual/domainowners" ]; then
echo "Error: Can't read /etc/virtual/domainowners"
exit 1
fi
if [ ! -r "/usr/local/directadmin/custombuild/options.conf" ]; then
echo "Error: Can't read /usr/local/directadmin/custombuild/options.conf"
exit 1
fi
function getAvailableReleases() {
# Fetch available releases as defined for DirectAdmin's custombuild
php_release[1]=$(grep -oP "^php1_release=\K.*(?=$)" /usr/local/directadmin/custombuild/options.conf)
php_release[2]=$(grep -oP "^php2_release=\K.*(?=$)" /usr/local/directadmin/custombuild/options.conf)
php_release[3]=$(grep -oP "^php3_release=\K.*(?=$)" /usr/local/directadmin/custombuild/options.conf)
php_release[4]=$(grep -oP "^php4_release=\K.*(?=$)" /usr/local/directadmin/custombuild/options.conf)
}
function getLongestDomainName() {
# Find the longest domain name, used for padding output later
domain_max_length=$(cat /etc/virtual/domainowners | cut -d":" -f1 | wc -L)
}
function printPhpSelections() {
for domain in $(cat /etc/virtual/domainowners | cut -d":" -f1); do
domainconffile=$(ls -1 /usr/local/directadmin/data/users/*/domains/${domain}.conf 2>&1 | head -1)
if [ ! -r "${domainconffile}" ]; then
# Domain has no config, and will use the default PHP version
# (php1_release), whatever it might be.
domain_active_version="${php_release[1]}:0"
domain_active_version_info="no config - using default"
else
# Fetch the php1_select for the domain
php_select[1]=$(grep -oP "^php1_select=\K.*(?=$)" ${domainconffile})
if [ -z "${php_select[1]}" ]; then
# Config has no php_select setting, and the domain will use the default PHP
# version (php1_release), whatever it might be.
domain_active_version="${php_release[1]}:0"
domain_active_version_info="no selection - using default"
else
domain_active_version="${php_release[${php_select[1]}]}:${php_select[1]}"
domain_active_version_info="selected version"
fi
fi
printf "%-$((domain_max_length+2))s %$((${#php_release[1]}+3))s %s\n" \
"${domain}" \
"${domain_active_version}" \
"(${domain_active_version_info})"
done
}
function setDomainPhpSelection() {
# Expected arguments:
# $1 = Domain config file, full path
# $2 = The new php selection number (not version)
local domainconffile accountdir domainname
domainconffile="${1}"
if [ -w "${domainconffile}" ]; then
# Update (or add) the php selection with the new release number
sed -i.backup_php_version_selections "/^php1_select=/{h;s/=.*/=${2}/};\${x;/^$/{s//php1_select=${2}/;H};x}" "${domainconffile}"
if [ "${?}" -eq 0 ]; then
echo "success"
else
echo "failure"
fi
else
# There's no config file for this domain. See if the domain is listed as
# a pointer for any other domain under this account.
accountdir="$(dirname ${domainconffile})"
domainname="$(basename ${domainconffile%.conf})"
grep -q "^${domainname//[.]/\\.}=" "${accountdir}/"*.pointers
if [ ${?} -eq 0 ]; then
# We found a match for the domain in a .pointers file
echo "pointer"
else
# It's not pointer, might be some other problem. Report as error so
# someone can manually check what's going on.
echo "wrerror"
fi
fi
}
function setPhpSelections() {
for domain in $(cat /etc/virtual/domainowners | cut -d":" -f1); do
domain_user=$(grep -oP "^${domain//[.]/\\.}: \K.+(?=$)" /etc/virtual/domainowners)
domain_config_file="/usr/local/directadmin/data/users/${domain_user}/domains/${domain}.conf"
# Look up the stored selections for this domain
domain_selected_version=$(grep -oP "^${domain//[.]/\\.} +\K[^:]+(?=:.*$)" "${selections_file}")
if [ ${?} -ne 0 ]; then
# If grep exited with non-zero, it likely means the domain doesn't
# exist in the selections_file, so we'll skip any further processing
# of this domain.
# domain.com 7.2:2 -> 7.2:3 changeresult (info)
printf "%-$((domain_max_length+2))s %s\n" \
"${domain}" \
"Skipping - domain not in selections file"
continue
fi
domain_selected_release=$(grep -oP "^${domain//[.]/\\.} +[^:]+:\K[0-9](?=.*$)" "${selections_file}")
domain_wanted_version="${domain_selected_version}:${domain_selected_release}"
# Find out which selection this version is now
domain_selected_release_new=""
for key in "${!php_release[@]}"; do
if [ "${domain_selected_version}" = "${php_release[${key}]}" ]; then
# This is the release selection we want. If the key is "1", then
# it's the default. If the domain_selected_release is 0, then we
# don't have to change anything, since the default is the same
# version.
if [ ${domain_selected_release} -eq 0 -a ${key} -eq 1 ]; then
domain_selected_release_new=0
else
domain_selected_release_new=${key}
fi
fi
done
if [ -z "${domain_selected_release_new}" ]; then
# The selected version no longer exist among the four options, so
# fall back to the default (php1_release) release/version.
# Must update the domain config.
domain_selected_release_new=1
domain_getting_version="${php_release[${domain_selected_release_new}]}:${domain_selected_release_new}"
domain_getting_version_info="default fallback - selected version no longer exists"
domain_release_change_result=$(setDomainPhpSelection "${domain_config_file}" "${domain_selected_release_new}")
elif [ "${domain_selected_release}" != "${domain_selected_release_new}" ]; then
# The version exists, but is now a different release number in the
# list.
# Must update the domain config.
domain_getting_version="${php_release[${domain_selected_release_new}]}:${domain_selected_release_new}"
domain_getting_version_info="version kept, selection changed"
domain_release_change_result=$(setDomainPhpSelection "${domain_config_file}" "${domain_selected_release_new}")
elif [ ${domain_selected_release_new} -eq 0 ]; then
# The version existed, and is (still) the default version. Nothing
# changes. No need to update anything.
domain_getting_version="${php_release[1]}:${domain_selected_release_new}"
domain_getting_version_info="default version kept, default selection kept"
domain_release_change_result="nochange"
else
# The version existed, and it's the same release as before, but not
# the default. No need to update anything.
domain_getting_version="${php_release[${domain_selected_release_new}]}:${domain_selected_release_new}"
domain_getting_version_info="version kept, selection kept"
domain_release_change_result="nochange"
fi
# domain.com 7.2:2 -> 7.2:3 changeresult (info)
printf "%-$((domain_max_length+2))s %$((${#php_release[1]}+3))s -> %-$((${#php_release[1]}+3))s %-9s %s\n" \
"${domain}" \
"${domain_wanted_version}" \
"${domain_getting_version}" \
"${domain_release_change_result}" \
"(${domain_getting_version_info})"
done
echo ""
echo "You will want to run /usr/local/directadmin/custombuild/build rewrite_confs now"
echo "to ensure all domains get their correct PHP version active."
}
getAvailableReleases
getLongestDomainName
# If there's an argument passed to the script, we assume it's the selections
# file, and we want the script to try to ensure the active selections match
# those described in the selections file. If there are no arguments, assume we
# want to create the selections list.
if [ ${#} -eq 0 ]; then
printPhpSelections
else
selections_file="${1}"
if [ ! -r "${selections_file}" ]; then
echo "Error: Can't read the file \"${selections_file}\". Pass the filename as the first argument."
exit 1
fi
echo "WARNING: Running this script will make changes to the following files:"
echo "/usr/local/directadmin/data/users/<username>/domains/<domain>.conf"
echo "In case it goes horribly wrong, please take a backup first."
read -p "Type 'RUN' in uppercase to proceed: " runit
if [ "${runit}" = "RUN" ]; then
echo
setPhpSelections
else
echo "Aborting script."
exit
fi
fi