#!/usr/bin/env bash readonly toolName=php readonly sq_repoUrl="https://packages.sury.org/php" # Already defined by sequencer.sh, but may be overwritten #readonly seq_configName="${sq_scriptName:?}.cfg" #readonly seq_configTemplate="${seq_origin:?}/${sq_configName:?}.example" sq_aptOpt= sq_config=0 sq_phpName=php sq_FpmConfig= sq_CliConfig= sq_PoolConfig= sq_FpmIni= seq_config() { if initSeqConfig "${seq_configName:?}" "${seq_configTemplate:?}" ; then sq_config=1 else # End if no configuration file exists dry || return 1 fi ## Apt cmdline option to suppress user interaction interactive || sq_aptOpt="-y" ## Disable error checks if external scripts are used ## e.g. error on unbound variables #disableErrorCheck sq_phpName="php${sc_phpVersion:?}" # Default dependencies for this seq sc_phpPackages+=(fpm cli) # Prepare php packages to be installed sq_phpPackages="${sc_phpPackages[@]/#/${sq_phpName}-}" sq_FpmConfig="/etc/php/${sc_phpVersion:?}/fpm/conf.d/90-custom_pi.ini" sq_CliConfig="/etc/php/${sc_phpVersion:?}/cli/conf.d/90-custom_pi.ini" sq_PoolConfig="/etc/php/${sc_phpVersion:?}/fpm/pool.d/www.conf" sq_FpmIni="/etc/php/${sc_phpVersion:?}/fpm/php-fpm.conf" ## Return of non zero value will abort the sequence return 0 } getPhpVersion() { local lPhp= if ! lPhp="$(command -v php >>/dev/null && php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')"; then return 1 fi echo ${lPhp} } step_1_info() { echo "Installation status"; } step_1_alias() { echo "status"; } step_1() { exe apt-cache policy ${sq_phpName}-common } step_3_info() { echo "Get installed PHP version"; } step_3_alias() { echo "version"; } step_3(){ if ! lPhp="$(getPhpVersion)" ; then warning "PHP not yet installed" return 1 fi echo "$lPhp" } step_5_info() { echoinfoArgs "[PHP_PACKAGE_NAME ...]" echo "Install ${toolName:-'-'} packages prepending the correct version" } step_5_alias() { echo "add"; } step_5() { shift local packages=("$@") (( ${#packages[@]} )) || fatal "No packages provided" exe apt install "${packages[@]/#/${sq_phpName}-}" ${sq_aptOpt:-} } step_10_info() { echo "Setup debian ${toolName:-'-'} repository"; } step_10_alias() { echo "setup"; } step_10() { local lArch= case $(uname -m) in aarch64) lArch=arm64;; esac if [[ -n ${lArch:-} ]] ; then info "Detected processor architecture: ${lArch}" lArch="[arch=${lArch}]" fi info "Installing custom repository prerequisites:" exe apt update exe apt install apt-transport-https lsb-release ca-certificates curl ${sq_aptOpt:-} info "Setup ${toolName:-'-'} repository including gpg key" exep curl -fsSL ${sq_repoUrl:?}/apt.gpg "|" gpg --dearmor -o /etc/apt/trusted.gpg.d/sury-keyring.gpg addConf -c "deb ${lArch:-} ${sq_repoUrl:?} $(lsb_release -sc) main" "/etc/apt/sources.list.d/php.list" exe apt-get update } step_11_info() { echo "Installation of ${toolName:-'-'} packages:" echoinfo "${sq_phpPackages:-"(customize with '${seq_name} -c')"}" } step_11_alias() { echo "install"; } step_11() { exe apt install ${sq_phpPackages} ${sq_aptOpt} } phpFpmConfig="date.timezone = Europe/Berlin max_execution_time = 600 memory_limit = 1024M output_buffering = Off session.cookie_secure = True upload_max_filesize = 1024M" phpCliConfig="date.timezone = Europe/Berlin output_buffering = Off" step_20_info() { echo "Configuration of ${sq_phpName} fpm and cli"; } step_20_alias() { echo "conf_fpm_cli"; } step_20() { addConf -s "$phpFpmConfig" "$sq_FpmConfig" addConf -s "$phpCliConfig" "$sq_CliConfig" restart_php } step_22_info() { echo "Configure ${toolName} pool ondemand"; } step_22_alias() { echo "conf_pool_ondemand"; } step_22() { info "Setting ${toolName} pool to 'ondemand'" addConf -a "" "$sq_FpmIni" exe sed -i "s/^[;[:space:]]*pm =.*/pm = ondemand/" "$sq_PoolConfig" restart_php } step_24_info() { echo "Configure ${toolName} pool dynamic"; } step_24_alias() { echo "conf_pool_dynamic"; } step_24() { local AvailableRAM=$(awk '/MemAvailable/ {printf "%d", $2/1024}' /proc/meminfo) local AverageFPM=$(ps --no-headers -o 'rss,cmd' -C php-fpm${sc_phpVersion} | awk '{ sum+=$1 } END { printf ("%d\n", sum/NR/1024,"M") }') local FPMS=$((AvailableRAM/AverageFPM)) local PMaxSS=$((FPMS*2/3)) local PMinSS=$((PMaxSS/2)) local PStartS=$(((PMaxSS+PMinSS)/2)) addConf -a "" "$sq_FpmIni" exe sed -i "s|;emergency_restart_threshold.*|emergency_restart_threshold = 10|g" "$sq_FpmIni" exe sed -i "s|;emergency_restart_interval.*|emergency_restart_interval = 1m|g" "$sq_FpmIni" exe sed -i "s|;process_control_timeout.*|process_control_timeout = 10|g" "$sq_FpmIni" addConf -a "" "$sq_PoolConfig" exe sed -i "s/;env\[HOSTNAME\] = /env[HOSTNAME] = /" "$sq_PoolConfig" exe sed -i "s/;env\[TMP\] = /env[TMP] = /" "$sq_PoolConfig" exe sed -i "s/;env\[TMPDIR\] = /env[TMPDIR] = /" "$sq_PoolConfig" exe sed -i "s/;env\[TEMP\] = /env[TEMP] = /" "$sq_PoolConfig" exe sed -i "s/;env\[PATH\] = /env[PATH] = /" "$sq_PoolConfig" exe sed -i "s/^[;[:space:]]*pm =.*/pm = dynamic/" "$sq_PoolConfig" exe sed -i 's/pm.max_children =.*/pm.max_children = '$FPMS'/' "$sq_PoolConfig" exe sed -i 's/pm.start_servers =.*/pm.start_servers = '$PStartS'/' "$sq_PoolConfig" exe sed -i 's/pm.min_spare_servers =.*/pm.min_spare_servers = '$PMinSS'/' "$sq_PoolConfig" exe sed -i 's/pm.max_spare_servers =.*/pm.max_spare_servers = '$PMaxSS'/' "$sq_PoolConfig" exe sed -i "s/;pm.max_requests =.*/pm.max_requests = 1000/" "$sq_PoolConfig" restart_php } restart_php() { info -n "Restarting ${sq_phpName} fpm ... " exe service ${sq_phpName}-fpm restart && info -d "ok" || info -d "nok" } # shellcheck disable=SC2034 # Appears unused readonly sqr_minVersion=16 # shellcheck disable=SC1091 # Don't follow this source . /usr/local/bin/sequencer.sh