Skip to content

Instantly share code, notes, and snippets.

@aklump
Last active February 18, 2025 00:07
Show Gist options
  • Save aklump/f9a30625826ec63cf3122778105cd63c to your computer and use it in GitHub Desktop.
Save aklump/f9a30625826ec63cf3122778105cd63c to your computer and use it in GitHub Desktop.
Xdebug Lando Controller
#!/usr/bin/env bash
#
# @file
# Xdebug Lando Controller (Supports Xdebug versions 2 and 3)
#
# Save this file to: ./install/lando/xdebug_controller.sh.
#
# This script is meant to be used for Lando tooling to control Xdebug. When
# using with version 2, use the version 3 syntax and it will be properly
# backported in config. Do not use version 2 syntax in php.ini.
#
# Usage examples:
# - lando xdebug on # Set xdebug mode = XDEBUG_MODE
# - lando xdebug off # Set mode to "off"
# - lando xdebug --mode # Print current mode
# - lando xdebug --version # Print Xdebug version
# - lando xdebug --config # Print Xdebug configuration
# - lando xdebug debug # Explicitly set the mode
# - lando xdebug debug,profile # Explicitly set multiple modes
#
# Optional, create the following bash aliases, or similar:
# @code
# alias lyb="lando xdebug on"
# alias lnb="lando xdebug off"
# @endcode
#
# Open .lando.yml and ensure these settings:
#
# @code
# config:
# xdebug: false
# config:
# php: install/lando/php.ini
# services:
# appserver:
# overrides:
# environment:
# XDEBUG_MODE: debug,develop
# XDEBUG_PORT: 9003
# tooling:
# 'xdebug [arg]':
# service: appserver
# description: Controls xdebug inside the container.
# cmd: "/app/install/lando/xdebug_controller.sh"
# user: root
# @endcode
#
# Open install/lando/php.ini and these optional settings as desired. You do not
# need to add xdebug.client_port or xdebug.remote_port to php.ini as this script
# uses XDEBUG_PORT for configurating that aspect.
# @code
# ; https://xdebug.org/docs/all_settings#output_dir
# ;xdebug.output_dir = /app/private/logs/xdebug/
#
# ; https://xdebug.org/docs/all_settings#log
# ; Uncomment xdebug.log only when you need to troubleshoot. Lando restart or
# ; rebuild is not required when you make this change.
# ;xdebug.log = /app/private/logs/xdebug/xdebug.log
#
# ; https://xdebug.org/docs/all_settings#log_level
# ;xdebug.log_level=7
#
# @endcode
#
# Finally use `lando rebuild` to catch all updates.
#
xdebug_config=/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
xdebug_user_config=/usr/local/etc/php/conf.d/zzz-lando-my-custom.xdebug_config.ini
function is_xdebug_enabled() {
[ -f "$xdebug_config" ]
}
function enable_xdebug() {
local target_mode="$1"
[[ "$(get_xdebug_mode)" == "$target_mode" ]] && return
is_xdebug_enabled || docker-php-ext-enable xdebug
# To support versions 2 and 3, we update both syntaxes.
! [ -e "$xdebug_user_config" ] || rm "$xdebug_user_config" || exit 1
# Version 3
# https://xdebug.org/docs/all_settings#mode
echo '; Xdebug Version 3' >> "$xdebug_user_config"
echo "xdebug.client_port=${XDEBUG_PORT:-9003}" >> "$xdebug_user_config"
echo "xdebug.mode = $target_mode" >> "$xdebug_user_config"
echo "xdebug.start_with_request = yes" >> "$xdebug_user_config"
echo >> "$xdebug_user_config"
# Version 2
# https://xdebug.org/docs/upgrade_guide#changed
echo '; Xdebug Version 2' >> "$xdebug_user_config"
echo "xdebug.remote_port=${XDEBUG_PORT:-9000}" >> "$xdebug_user_config"
line="xdebug.default_enable"
[[ "$target_mode" =~ "develop" ]] && line="$line = 1" || line="$line = 0"
echo "$line" >> "$xdebug_user_config"
line="xdebug.coverage_enable"
[[ "$target_mode" =~ "coverage" ]] && line="$line = 1" || line="$line = 0"
echo "$line" >> "$xdebug_user_config"
line="xdebug.remote_enable"
[[ "$target_mode" =~ "debug" ]] && line="$line = 1" || line="$line = 0"
echo "$line" >> "$xdebug_user_config"
line="xdebug.profiler_enable"
[[ "$target_mode" =~ "profile" ]] && line="$line = 1" || line="$line = 0"
echo "$line" >> "$xdebug_user_config"
line="xdebug.auto_trace"
[[ "$target_mode" =~ "trace" ]] && line="$line = 1" || line="$line = 0"
echo "$line" >> "$xdebug_user_config"
echo "xdebug.remote_start = 1" >> "$xdebug_user_config"
# https://drupal.stackexchange.com/a/315971/26195
pgrep php-fpm >/dev/null 2>&1 && pkill -o -USR2 php-fpm
service apache2 status >/dev/null 2>&1 && service apache2 reload
}
function disable_xdebug() {
! is_xdebug_enabled && return
# Remove the xdebug configuration && then restart servers without it.
rm "$xdebug_user_config" "$xdebug_config"
# https://drupal.stackexchange.com/a/315971/26195
pgrep php-fpm >/dev/null 2>&1 && pkill -o -USR2 php-fpm
service apache2 status >/dev/null 2>&1 && service apache2 reload
}
function get_xdebug_mode() {
version=$(get_xdebug_version)
! [[ "$version" ]] && echo "off" && return
if [[ "$version" =~ ^2\.+ ]]; then
_get_mode_v2
elif [[ "$version" =~ ^3\. ]]; then
_get_mode_v3
fi
}
function _get_mode_v2() {
local mode
match=($(php -i | grep 'xdebug.default_enable => On'))
[[ "${match[2]}" ]] && mode="$mode,develop"
match=($(php -i | grep 'xdebug.coverage_enable => On'))
[[ "${match[2]}" ]] && mode="$mode,coverage"
match=($(php -i | grep 'xdebug.remote_enable => On'))
[[ "${match[2]}" ]] && mode="$mode,debug"
match=($(php -i | grep 'xdebug.profiler_enable => On'))
[[ "${match[2]}" ]] && mode="$mode,profile"
match=($(php -i | grep 'xdebug.trace => On'))
[[ "${match[2]}" ]] && mode="$mode,auto_trace"
echo ${mode#,}
}
function _get_mode_v3() {
mode=($(php -i | grep 'xdebug.mode =>'))
mode=${mode[2]}
if [[ ! "$mode" ]] || [[ "$mode" == 'no' ]]; then
mode="off"
fi
echo $mode
}
function get_xdebug_version() {
version=($(php -i | grep 'with Xdebug v'))
version=${version[2]#v}
echo ${version%,}
}
function handle_mode() {
local mode="$1"
if [[ "$mode" == "off" ]]; then
disable_xdebug
else
[[ "$mode" == "on" ]] && mode="${XDEBUG_MODE:-debug}"
enable_xdebug "$mode"
fi
}
function handle_show_mode() {
get_xdebug_mode && exit 0
}
function handle_show_config() {
[ -e "$xdebug_user_config" ] && cat "$xdebug_user_config"
exit 0
}
function handle_show_version() {
is_xdebug_enabled && get_xdebug_version && return
enable_xdebug on
get_xdebug_version
disable_xdebug
exit 0
}
#
# END FUNCTIONS
# BEGIN CONTROLLER
#
case $1 in
'--mode')
handle_show_mode
;;
'--config')
handle_show_config
;;
'--version' | '-v')
handle_show_version
;;
*)
handle_mode "$1"
;;
esac
# Give feedback to the user of the final PHP config.
echo -e "\n\e[1;97;42mxdebug.mode = $(get_xdebug_mode)\e[0m\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment