Last active
February 18, 2025 00:07
-
-
Save aklump/f9a30625826ec63cf3122778105cd63c to your computer and use it in GitHub Desktop.
Xdebug Lando Controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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