HEX
Server: nginx/1.29.3
System: Linux 11979.bigscoots-wpo.com 6.8.0-88-generic #89-Ubuntu SMP PREEMPT_DYNAMIC Sat Oct 11 01:02:46 UTC 2025 x86_64
User: nginx (1068)
PHP: 7.4.33
Disabled: exec,system,passthru,shell_exec,proc_open,proc_close,popen,show_source,cmd# Do not modify this line # 1684243876
Upload Files
File: //bigscoots/wpo/phpfpm/multiphp.sh
#!/bin/bash

# This script is used to manage PHP installations
# and configuration for different domains.
# Using Remi Repo

if [[ -f /bigscoots/php-pools/php-pools ]]; then
  if [ "$#" -ne 5 ]; then
    echo "invalid arg len" >&2
    exit 2
  fi

  /bigscoots/php-pools/php-pools set $3 $5

  exit 0
fi

source /bigscoots/includes/common.sh

# Function to send Slack alert
send_slack_alert_cust() {
    local message="$1"
    bash /bigscoots/general/slack.sh "#wpo-alerts" ":warning: *WPO MultiPHP*\n*Hostname:* $(hostname)\n *Server IP:* ${serverip}\n *Message:* ${message}"
}

# Function to log actions
log_action() {
    local message="$1"
    echo "$(date +"%Y-%m-%d %H:%M:%S") : ${message}" >> /root/.bigscoots/logs/multiphp.log
}

update_php_config() {
	local phpver="$1"
	local php_conf_path="/etc/opt/remi/${phpver}/php-fpm.d/www.conf"
	local custom_php_ini="/etc/opt/remi/${phpver}/php.d/zzz_customphp.ini"
	local bsdomains_ini="/etc/centminmod/php.d/bsdomains.ini"
	local opcache_blacklist="/etc/opt/remi/${phpver}/php.d/opcache-default.blacklist"

	# Remve unnecesasry lines
	sed -i '/^$/d ; /^;/d ; /php_admin_value\[error_log\]/d ; /php_admin_flag\[log_errors\]/d' "$php_conf_path"
	sed -i '/pm.start_servers/d ; /pm.min_spare_servers/d ; /pm.max_spare_servers/d' "$php_conf_path"

	sed -i '/pm =/c\pm = ondemand' "$php_conf_path"
	sed -i '/slowlog =/c\slowlog = /var/log/php-fpm/www-slow.log' "$php_conf_path"

	if ! grep -q "request_slowlog_timeout" "$php_conf_path"
	then 
	    sed -i '/slowlog =/i request_slowlog_timeout = 20' "$php_conf_path"
	fi
	
	if [[ $2 == maxchild ]]
	then
		max_children=$(grep -v '^\s*;' /usr/local/etc/php-fpm.conf | grep pm.max_children | grep -o '[0-9]\+')
		if [[ $max_children =~ ^[0-9]+$ ]]
		then
			sed -i "/pm.max_children/c\pm.max_children = $max_children" "$php_conf_path"
		fi
	fi

	if ! grep -q "pm.max_requests" "$php_conf_path"
	then 
	    sed -i '/pm.max_children/a\pm.max_requests = 25' "$php_conf_path"
	fi

	if grep -q pcre.jit "$custom_php_ini"
	then 
	    sed -i '/pcre.jit/c\pcre.jit=1' "$custom_php_ini"
	else 
	    echo "pcre.jit=1" >> "$custom_php_ini"
	fi

	if grep -q date.timezone "$custom_php_ini"
	then 
	    sed -i '/date.timezone/c\date.timezone = \"America/Chicago\"' "$custom_php_ini"
	else 
	    echo "date.timezone = \"America/Chicago\"" >> "$custom_php_ini"
	fi

	if [ -f "$bsdomains_ini" ]
	then
	    ln -fs "$bsdomains_ini" "/etc/opt/remi/${phpver}/php.d/"
	fi

	if [ ! -L "$opcache_blacklist" ]
	then
		ln -fs /root/.bigscoots/php/opcache-blacklist.txt "$opcache_blacklist"
	fi
}

allinfo() {
  specific_domain=$1  # The specific domain argument passed (if any)
  
  # Check if a specific domain is passed and if it exists
  if [ -n "$specific_domain" ]
  then
    if [ ! -d "/home/nginx/domains/$specific_domain" ]
    then
      echo "Error: The specified domain does not exist."
      return 1
    fi
    domains=($specific_domain)
  else
    # Get all domains if none specified
    domains=($(find /home/nginx/domains/ -mindepth 1 -maxdepth 1 -type d -not -path '*/\.*' -name '*.*' | sed 's|/home/nginx/domains/||g'))
  fi

    for domain in "${domains[@]}"; do
        DPHPV=$(grep -i "^ \+ include /usr/local/nginx/conf/php" "/usr/local/nginx/conf/conf.d/${domain}.ssl.conf" | awk '{print $2}' | sort | uniq)
        
        if [[ $(grep -i "^ \+ include /usr/local/nginx/conf/php" "/usr/local/nginx/conf/conf.d/${domain}.ssl.conf" | awk '{print $2}' | sort | uniq | wc -l) -gt 1 ]]
        then
            echo "Detected multiple versions of PHP in /usr/local/nginx/conf/conf.d/${domain}.ssl.conf please fix."
        elif [[ $DPHPV == *"php-wpsc.conf"* ]]
    	then
            echo "Native PHP: $(php -v 2>/dev/null | head -1 | awk '{print $2}') - ${domain}"
        elif [[ $DPHPV == *"php-fastcgicache.conf"* ]]
    	then
            echo "Native PHP: $(php -v 2>/dev/null | head -1 | awk '{print $2}') with FastCGI caching - ${domain}"
        elif [[ "$DPHPV" =~ php[0-9][0-9]-remi.conf ]]
    	then
            echo "Multi PHP: $(/opt/remi/php$(echo $DPHPV | sed 's|/usr/local/nginx/conf/php||g ; s|-remi.conf;||g')/root/bin/php -v 2>/dev/null | head -1 | awk '{print $2}') - ${domain}"
        elif [[ "$DPHPV" =~ php-fastcgicache[0-9][0-9].conf ]]
    	then
            echo "Multi PHP: $(/opt/remi/php$(echo $DPHPV | sed 's|/usr/local/nginx/conf/php||g ; s|-remi.conf;||g')/root/bin/php -v 2>/dev/null | head -1 | awk '{print $2}') with FastCGI caching - ${domain}"
        else
            echo "Not sure what PHP version is running, using a custom config? - ${domain}"
        fi
    done
}

update_php_versions_json() {
    local json_file="/root/.bigscoots/php_versions.json"
    local domain=$1
    local php_version=""

    # Determine PHP version for each domain
    DPHPV=$(grep -i "^ \+ include /usr/local/nginx/conf/php" "/usr/local/nginx/conf/conf.d/${domain}.ssl.conf" | awk '{print $2}' | sort | uniq)

    if [[ $DPHPV == *"php74-remi.conf"* ]]; then
        php_version="7.4"
    elif [[ $DPHPV == *"php81-remi.conf"* ]]; then
        php_version="8.1"
    elif [[ $DPHPV == *"php82-remi.conf"* ]]; then
        php_version="8.2"
    else
        php_version="native"
    fi

    # Update the JSON file with the new PHP version
    if [[ -f $json_file ]]; then
        jq --arg domain "$domain" --arg php_version "$php_version" '.[$domain] = $php_version' $json_file > temp.json && mv temp.json $json_file
    else
        echo "{\"$domain\": \"$php_version\"}" > $json_file
    fi
}

generate_nginx_map() {
    local json_file="/root/.bigscoots/php_versions.json"
    local nginx_map="/usr/local/nginx/conf/php_map.conf"

    # Start the map block
    echo "map \$host \$php_conf {" > $nginx_map
    echo "    default \"/usr/local/nginx/conf/php-wpsc.conf\";" >> $nginx_map

    # Read the JSON file and generate the map entries
    jq -r 'to_entries[] | if .value == "native" then "    \(.key) \"/usr/local/nginx/conf/php-wpsc.conf\";" else "    \(.key) \"/usr/local/nginx/conf/php\(.value | gsub("\\."; ""))-remi.conf\";" end' $json_file >> $nginx_map

    # Close the map block
    echo "}" >> $nginx_map

    # Reload NGINX to apply changes
    nginx -t && systemctl reload nginx
}

phpinstall() {
		if [ ! -d /root/.biscoots ]
		then
			mkdir -p /root/.bigscoots
		fi

		if [ -d /root/.bigscoots/centminmod-multiphp ]
		then
			git --git-dir=/root/.bigscoots/centminmod-multiphp/.git --work-tree=/root/.bigscoots/centminmod-multiphp pull
		else
			if ! git_clone_output=$(git clone https://github.com/jcatello/centminmod-multiphp /root/.bigscoots/centminmod-multiphp 2>&1)
			then
				send_slack_alert_cust "Git clone of repo https://github.com/jcatello/centminmod-multiphp failed.\nError:\`\`\`${git_clone_output}\`\`\`"
			fi
		fi

		if grep -q "CentOS" /etc/redhat-release; then
		    skip_php84=true
		else
		    skip_php84=false
		fi

		ls -1 /root/.bigscoots/centminmod-multiphp/php[0-9][0-9].sh | sed 's/.sh//g' | grep 'php74\|php81\|php82\|php83\|php84\|php85' | xargs -n 1 basename | while read -r phpver
		do
		    # Skip php84 if running CentOS
            if [ "$skip_php84" = true ] && { [ "$phpver" = "php84" ] || [ "$phpver" = "php85" ]; }; then
                continue
            fi

		    # "Checking to see if PHP ${phpver} installed"
		    if ! bash /root/.bigscoots/centminmod-multiphp/"${phpver}".sh status >/dev/null 2>&1
		    then
		        yum_check
		        if [ -f "/etc/opt/remi/${phpver}/php-fpm.d/www.conf" ]
		        then
		            bash /root/.bigscoots/centminmod-multiphp/"${phpver}".sh install >/dev/null 2>&1
		            update_php_config "${phpver}"
		            bash /root/.bigscoots/centminmod-multiphp/"${phpver}".sh restart
		        else
		            bash /root/.bigscoots/centminmod-multiphp/"${phpver}".sh install >/dev/null 2>&1
		            update_php_config "${phpver}" maxchild
		            bash /root/.bigscoots/centminmod-multiphp/"${phpver}".sh restart
		        fi
		    else
		        update_php_config "${phpver}"
		    fi
		done

		find /var/opt/remi/php*/lib/php -group apache -exec chgrp nginx {} \;

		bash /bigscoots/wpo/phpfpm/create_pools.sh
		# Add action to log
		log_action "PHP Install completed successfully"
}

checkphp() {
    if [[ -z "$domain" || -z "$phpver" ]]; then
        echo "{\"success\": false, \"error\": \"Domain or PHP version is not set.\"}" 
        echo "Error: domain or phpver is not set." >> /root/.bigscoots/logs/multiphp.log
        exit 1
    elif [[ "$phpver" == 'native' ]]; then
        echo "{\"success\": true, \"message\": \"PHP Version is set to 'native.' Skipping PHP installation.\"}"
        echo "PHP Version is set to 'native.' Skipping PHP installation." >> /root/.bigscoots/logs/multiphp.log
        return
    fi

    validate_domain_in_path "$domain" multiphp.sh || { 
        echo "{\"success\": false, \"error\": \"Domain has failed validation!\"}"
        echo "Domain validation failed for $domain" >> /root/.bigscoots/logs/multiphp.log
        exit 1
    }

    if [ ! -d /root/.bigscoots/centminmod-multiphp ]; then
    	phpinstall
    fi

    echo "Checking required PHP files for PHP $phpver..." >> /root/.bigscoots/logs/multiphp.log
    required_files=(
        "/root/.bigscoots/centminmod-multiphp/php${phpver}.sh"
        "/usr/bin/php${phpver}"
        "/etc/opt/remi/php${phpver}/php-fpm.d/www.conf"
        "/etc/opt/remi/php${phpver}/php.d/zzz_customphp.ini"
        "/etc/opt/remi/php${phpver}/php.ini"
        "/var/opt/remi/php${phpver}/log/php-fpm/www-error.log"
        "/usr/local/nginx/conf/php${phpver}-remi.conf"
        "/etc/yum.repos.d/remi.repo"
    )

    missing_files=()
    for file in "${required_files[@]}"; do
        if [[ ! -f "$file" ]]; then
            missing_files+=("$file")
        fi
    done

    if [[ ${#missing_files[@]} -gt 0 ]]; then
        echo "Missing files detected for PHP ${phpver}:" >> /root/.bigscoots/logs/multiphp.log
        printf '%s\n' "${missing_files[@]}" >> /root/.bigscoots/logs/multiphp.log
        echo "Running PHP ${phpver} installer script..." >> /root/.bigscoots/logs/multiphp.log
        git --git-dir=/root/.bigscoots/centminmod-multiphp/.git --work-tree=/root/.bigscoots/centminmod-multiphp pull >/dev/null 2>&1
        bash /root/.bigscoots/centminmod-multiphp/php"${phpver}".sh install >/dev/null 2>&1
    else
        echo "All required files exist for PHP $phpver." >> /root/.bigscoots/logs/multiphp.log
    fi

    attempt=1
    while true; do
        echo "Checking if PHP $phpver is running (Attempt: $attempt)..." >> /root/.bigscoots/logs/multiphp.log
        if ! bash /root/.bigscoots/centminmod-multiphp/php"${phpver}".sh status >/dev/null 2>&1; then
            echo "PHP $phpver not running, reinstalling..." >> /root/.bigscoots/logs/multiphp.log
            git --git-dir=/root/.bigscoots/centminmod-multiphp/.git --work-tree=/root/.bigscoots/centminmod-multiphp pull >/dev/null 2>&1
            bash /root/.bigscoots/centminmod-multiphp/php"${phpver}".sh install >/dev/null 2>&1
            if ! bash /root/.bigscoots/centminmod-multiphp/php"${phpver}".sh status >/dev/null 2>&1; then
                echo "PHP $phpver failed to install after retry." >> /root/.bigscoots/logs/multiphp.log
                echo "{\"success\": false, \"error\": \"PHP Version installation failed for ${phpver}\"}"
                exit 1
            else
                break
            fi
        else
            echo "PHP $phpver is running successfully." >> /root/.bigscoots/logs/multiphp.log
            break
        fi

        attempt=$((attempt + 1))
        if [[ $attempt -gt 1 ]]; then
            echo "PHP Version change failed!" >> /root/.bigscoots/logs/multiphp.log
            send_slack_alert_cust "PHP Version change failed for \`${phpver}\`."
            echo "{\"success\": false, \"error\": \"PHP Version change failed for ${phpver}\"}"
            exit 1
        fi
    done
}

setphp() {
	validate_domain_in_path "$domain" multiphp.sh || { echo "{\"success\": false, \"error\": \"Domain has failed validation!\"}"; exit 1; }
  if ls -1 /home/nginx/domains/ | grep -q "$domain" && [[ "$phpver" == *'56'* || $phpver == *'70'* || $phpver == *'71'* || $phpver == *'72'* || $phpver == *'73'* || $phpver == *'74'* || $phpver == *'80'* || $phpver == *'81'* || $phpver == *'82'* || $phpver == *'83'* || $phpver == *'84'* || $phpver == *'85'* || $phpver == *'native'* ]]
  then
    SSLCONF="/usr/local/nginx/conf/conf.d/${domain}.ssl.conf"
    WPSECURECONF="/usr/local/nginx/conf/wpincludes/${domain}/wpsecure_${domain}.conf"
    
    if [[ "$phpver" == 'native' ]]
    then
    	PHPCONF="/usr/local/nginx/conf/php-wpsc.conf"
  	else
    	PHPCONF="/usr/local/nginx/conf/php${phpver}-remi.conf"
  	fi


    if [[ -f ${PHPCONF} ]]
    then
      if ! sed_output=$(sed -ri "s#/usr/local/nginx/conf/(php.conf|php-wpsc.conf|php[0-9]{2}-remi.conf)#${PHPCONF}#g" "${SSLCONF}" "${WPSECURECONF}" 2>&1)
      then
       	echo "{\"success\": false, \"error\": \"PHP Version changed failed, contacting support!\"}"
	    	send_slack_alert_cust "Replacing phpver using sed failed in files: \n\`${SSLCONF}\`\n \`${WPSECURECONF}\`\n *Error:*\`\`\`${sed_output}\`\`\`"
        exit 1
      fi
    else
    	echo "{\"success\": false, \"error\": \"PHP Version changed failed, contacting support!\"}"
    	send_slack_alert_cust "${PHPCONF} is missing."
    	exit 1
    fi
  fi

  # Add action to log
  log_action "PHP version for $domain set to $phpver successfully"
}

nginxreload() {
		if nginx -t > /dev/null 2>&1
		then
			ngxreload > /dev/null 2>&1
		else
			send_slack_alert_cust "Nginx Conf failed after changing PHP on $domain to PHP ${phpver} \n \`\`\`$(nginx -t 2>&1)\`\`\`"
			echo "{\"success\": false, \"error\": \"PHP Version changed failed, contacting support!\"}"
			exit 1
		fi

		# Add action to log
		log_action "Nginx reloaded successfully"
}

update_wpo_api() {
    # sync php version wpo api endpoint
    URL="https://patchstack-wpo.bigscoots.com/versions/sync_php_version"

    AUTHORIZATION=$(get_wpo_api_hash)

    # Get the JSON data from the info.sh script
    DATA=$(bash /bigscoots/wpo/manage/info.sh --domain $domain phpver)

    # Send the POST request using curl with quiet mode (-s) and store the response in a variable
    response=$(curl -s -X POST -H "Authorization: ${AUTHORIZATION}" -H "Content-Type: application/json" -d "${DATA}" "${URL}")

    # Check the response for success or failure
    if ! echo "$response" | grep -q '"success":true'
    then
    	escaped_response=$(echo "$response" | sed 's/"/\\"/g')
    	send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_wpo_api\`" "$domain" "\`\`\`$escaped_response\`\`\`"
    fi
}

update_php() {
	# Check if /opt/remi/php* folders exist
	if ls -d /opt/remi/php* >/dev/null 2>&1
	then
		# Get the list of PHP versions
		php_versions=(/opt/remi/php*/)

		# Loop through each PHP version and run the update script
		for php_path in "${php_versions[@]}"
		do
			phpver="$(basename "$php_path")"
			bash /root/.bigscoots/centminmod-multiphp/"$phpver".sh update
		done

	  if [[ "$REBOOT" == true ]]
	  then
	      bash /bigscoots/wpo/manage/php.sh --reboot
	  else
	      bash /bigscoots/wpo/manage/php.sh
	  fi
	fi
}

## Enable PHP‑FPM access logging ##
enable_access_logs() {
  local logs=()

  for pool in /etc/opt/remi/php*/php-fpm.d/www.conf; do
    [[ -f "$pool" ]] || continue

    version="${pool#*/php}"
    version="${version%%/*}"

    logdir="/var/opt/remi/php${version}/log/php-fpm"
    logfile="${logdir}/access.log"
    mkdir -p "$logdir"

    if ! grep -q '^access\.log' "$pool"; then
      cat <<EOF >> "$pool"

access.log = ${logfile}
access.format = "%{HTTP_X_FORWARDED_FOR}e - [%t] \"%m %r%Q%q\" %s %l - %P %p %{seconds}d %{bytes}M %{user}C%% %{system}C%% \"%{REQUEST_URI}e\" \"%{HTTP_USER_AGENT}e\" %{HTTP_HOST}e"
EOF
      scoots php reload all > /dev/null 2>&1
    fi

    logs+=("$logfile")
  done

  echo "Access log files are located at:"
  for lf in "${logs[@]}"; do
    echo "  $lf"
  done
}

show_help() {
cat << EOF
Usage: $0 COMMAND [OPTIONS]

Commands:
  set               Set PHP version for a domain
  info              Display PHP information
  check             Check PHP installs
  update_configs    Update PHP configs
  enable-logs       Enable PHP‑FPM access logs
  update            Update all PHP versions

Options:
  --domain DOMAIN
  --phpver PHPVER
  --bulk
  --reboot
EOF
}

BULK=false
REBOOT=false

# Initialize JSON string
json_output="{\"success\": true, "

# Parse command line arguments
command=$1
shift
while (( "$#" ))
do
  case "$1" in
		--domain)
	  	domain=$2
		  json_output+="\"domain\": \"$domain\","
		  shift 2 # Remove --domain and the actual domain
	 		;;
		--phpver)
	  	phpver=$2
		  json_output+="\"phpver\": \"$phpver\","
		  shift 2 # Remove --phpver and the actual phpver
	  	;;
		--bulk)
			BULK=true
		  shift # skip nginx check
	  	;;
		--reboot)
			REBOOT=true
		  shift # skip nginx check
	  	;;
    *)
      echo "Invalid command"
      show_help
      exit 1
      ;;
  esac
done

case $command in
  set)
		fix_mariadb103_repo
		[[ "$BULK" == false ]] && checkphp
		setphp
		[[ "$BULK" == false ]] && nginxreload
		update_wpo_api
    ;;
  info)
		allinfo "$domain"  # Pass $2 (if it exists) to allinfo
    ;;
  check)
		checkphp
    ;;
  update_configs)
		fix_mariadb103_repo
		phpinstall
    ;;
  update)
		fix_mariadb103_repo
		update_php
		phpinstall
    ;;
  enable-logs)
    enable_access_logs
    ;;
  v2_gen_json)
		domains=($(find /home/nginx/domains/ -mindepth 1 -maxdepth 1 -type d -not -path '*/\.*' -name '*.*' | sed 's|/home/nginx/domains/||g'))
		# Iterate over domains and update JSON file
		for domain in "${domains[@]}"; do
		    update_php_versions_json "$domain"
		done
		generate_nginx_map
    ;;	
  *)
    echo "Invalid command"
    show_help
    exit 1
    ;;
esac

# Remove trailing comma and close JSON object
json_output=$(echo "$json_output" | sed 's/,$//')
json_output+="}"

echo "$json_output"