Allow host:port syntax for --debug in kc.sh (#39924)

* Allow host:port syntax for --debug in kc.sh

Loosen the --debug argument parsing in kc.sh to accept full host:port
addresses (e.g. 0.0.0.0:8787 or *:8787) in addition to plain port
numbers. This enables JDWP to bind to all container interfaces when
running Keycloak in Docker, without requiring manual JAVA_OPTS overrides
or script edits.

Closes #38924

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Handle IPv6 address in --debug parameter in kc.sh

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Handle both bare and bracketed IPv6 addresses in kc.sh --debug parameter

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Handle corner cases in kc.sh --debug parameter IPv6 address handling

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Simplify kc.sh --debug parameter parsing, assume bracketed IPv6 addresses

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Remove final else case to avoid consuming following parameters

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Standardize indentation in kc.bat script

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Allow host:port syntax for --debug in kc.bat

Signed-off-by: mircea.talu <talumircea13@gmail.com>

* Add documentation for host:port usage in --debug parameter

Signed-off-by: mircea.talu <talumircea13@gmail.com>

---------

Signed-off-by: mircea.talu <talumircea13@gmail.com>
Co-authored-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
Mircea Talu 2025-07-03 19:34:17 +03:00 committed by GitHub
parent c52edc853d
commit c315762883
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 104 additions and 83 deletions

View File

@ -104,7 +104,7 @@ The `kc.sh|bat` script allows you to remotely debug the distribution. For that,
kc.sh --debug start-dev
```
By default, the debug port is available at `8787`.
By default, the debug port is available at `8787`. Additionally, you can specify IPv4 or bracketed IPv6 addresses with optional ports, e.g. `--debug 127.0.0.1`, `--debug 127.0.0.1:8786`, `--debug [::1]`, `--debug [::1]:8785`. Make sure to exercise caution when setting IP addresses in the `--debug` parameter, since a value such as `--debug 0.0.0.0:8787` will expose the debug port to all network interfaces!
An additional environment variable `DEBUG_SUSPEND` can be set to suspend the JVM, when launched in debug mode. The `DEBUG_SUSPEND` variable supports the following values:

View File

@ -8,21 +8,22 @@ setlocal
rem Get the program name before using shift as the command modify the variable ~nx0
if "%OS%" == "Windows_NT" (
set PROGNAME=%~nx0%
set PROGNAME=%~nx0%
) else (
set PROGNAME=kc.bat
set PROGNAME=kc.bat
)
if "%OS%" == "Windows_NT" (
set "DIRNAME=%~dp0"
set "DIRNAME=%~dp0"
) else (
set DIRNAME=.\
set DIRNAME=.\
)
set SERVER_OPTS=-Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dquarkus-log-max-startup-records=10000 -Dpicocli.disable.closures=true
set DEBUG_MODE=false
set DEBUG_PORT_VAR=8787
set DEBUG_ADDRESS=0.0.0.0:%DEBUG_PORT_VAR%
set DEBUG_SUSPEND_VAR=n
set CONFIG_ARGS=
@ -33,20 +34,29 @@ if "%KEY%" == "" (
goto MAIN
)
if "%KEY%" == "--debug" (
set DEBUG_MODE=true
if 1%2 EQU +1%2 (
set DEBUG_PORT_VAR=%2
shift
) else (
set DEBUG_PORT_VAR=8787
)
shift
goto READ-ARGS
set DEBUG_MODE=true
if 1%2 EQU +1%2 (
rem Plain port
set DEBUG_ADDRESS=0.0.0.0:%2
shift
) else (
rem IPv4 or IPv6 address with optional port
(echo %2 | findstr /R "[0-9].*\." >nul || echo %2 | findstr /R "\[.*:.*\]" >nul) && (
(echo %2 | findstr /R "]:[0-9][0-9]*" >nul || echo %2 | findstr /R "^[0-9].*:[0-9][0-9]*" >nul) && (
set DEBUG_ADDRESS=%2
) || (
set DEBUG_ADDRESS=%2:%DEBUG_PORT_VAR%
)
shift
)
)
shift
goto READ-ARGS
)
if "%KEY%" == "start-dev" (
set CONFIG_ARGS=%CONFIG_ARGS% --profile=dev %KEY%
shift
goto READ-ARGS
set CONFIG_ARGS=%CONFIG_ARGS% --profile=dev %KEY%
shift
goto READ-ARGS
)
set "VALUE=%~2"
set PROBABLY_VALUE=false
@ -58,25 +68,25 @@ if "%VALUE%" NEQ "" (
)
)
if "%KEY:~0,2%"=="-D" (
if %PROBABLY_VALUE%==true (
set SERVER_OPTS=%SERVER_OPTS% %KEY%^=%VALUE%
if %PROBABLY_VALUE%==true (
set SERVER_OPTS=%SERVER_OPTS% %KEY%^=%VALUE%
shift
) else (
set SERVER_OPTS=%SERVER_OPTS% %KEY%
)
shift
) else (
set SERVER_OPTS=%SERVER_OPTS% %KEY%
)
shift
goto READ-ARGS
goto READ-ARGS
)
if not "%KEY:~0,1%"=="-" (
set CONFIG_ARGS=%CONFIG_ARGS% %1
shift
goto READ-ARGS
set CONFIG_ARGS=%CONFIG_ARGS% %1
shift
goto READ-ARGS
)
if %PROBABLY_VALUE%==true (
set CONFIG_ARGS=%CONFIG_ARGS% %1 %2
shift
set CONFIG_ARGS=%CONFIG_ARGS% %1 %2
shift
) else (
set CONFIG_ARGS=%CONFIG_ARGS% %1
set CONFIG_ARGS=%CONFIG_ARGS% %1
)
shift
goto READ-ARGS
@ -86,91 +96,90 @@ goto READ-ARGS
setlocal EnableDelayedExpansion
if not "x%JAVA_OPTS%" == "x" (
echo "JAVA_OPTS already set in environment; overriding default settings"
echo "JAVA_OPTS already set in environment; overriding default settings"
) else (
rem The defaults set up Keycloak with '-XX:+UseG1GC -XX:MinHeapFreeRatio=40 -XX:MaxHeapFreeRatio=70 -XX:GCTimeRatio=12 -XX:AdaptiveSizePolicyWeight=10' which proved to provide a good throughput and efficiency in the total memory allocation and CPU overhead.
rem If the memory is not used, it will be freed. See https://developers.redhat.com/blog/2017/04/04/openjdk-and-containers for details.
rem To optimize for large heap sizes or for throughput and better response time due to shorter GC pauses, consider ZGC and Shenandoah GC.
rem As of KC25 and JDK17, G1GC, ZGC and Shenandoah GC seem to be eager to claim the maximum heap size. Tests showed that ZGC might need additional tuning in reclaiming dead objects.
set "JAVA_OPTS=-XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/urandom -XX:+UseG1GC -XX:FlightRecorderOptions=stackdepth=512"
rem The defaults set up Keycloak with '-XX:+UseG1GC -XX:MinHeapFreeRatio=40 -XX:MaxHeapFreeRatio=70 -XX:GCTimeRatio=12 -XX:AdaptiveSizePolicyWeight=10' which proved to provide a good throughput and efficiency in the total memory allocation and CPU overhead.
rem If the memory is not used, it will be freed. See https://developers.redhat.com/blog/2017/04/04/openjdk-and-containers for details.
rem To optimize for large heap sizes or for throughput and better response time due to shorter GC pauses, consider ZGC and Shenandoah GC.
rem As of KC25 and JDK17, G1GC, ZGC and Shenandoah GC seem to be eager to claim the maximum heap size. Tests showed that ZGC might need additional tuning in reclaiming dead objects.
set "JAVA_OPTS=-XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/urandom -XX:+UseG1GC -XX:FlightRecorderOptions=stackdepth=512"
if "x%JAVA_OPTS_KC_HEAP%" == "x" (
if "!KC_RUN_IN_CONTAINER!" == "true" (
rem Maximum utilization of the heap is set to 70% of the total container memory
rem Initial heap size is set to 50% of the total container memory in order to reduce GC executions
set "JAVA_OPTS_KC_HEAP=-XX:MaxRAMPercentage=70 -XX:MinRAMPercentage=70 -XX:InitialRAMPercentage=50"
if "x%JAVA_OPTS_KC_HEAP%" == "x" (
if "!KC_RUN_IN_CONTAINER!" == "true" (
rem Maximum utilization of the heap is set to 70% of the total container memory
rem Initial heap size is set to 50% of the total container memory in order to reduce GC executions
set "JAVA_OPTS_KC_HEAP=-XX:MaxRAMPercentage=70 -XX:MinRAMPercentage=70 -XX:InitialRAMPercentage=50"
) else (
set "JAVA_OPTS_KC_HEAP=-Xms64m -Xmx512m"
)
) else (
set "JAVA_OPTS_KC_HEAP=-Xms64m -Xmx512m"
echo "JAVA_OPTS_KC_HEAP already set in environment; overriding default settings"
)
) else (
echo "JAVA_OPTS_KC_HEAP already set in environment; overriding default settings"
)
set "JAVA_OPTS=!JAVA_OPTS! !JAVA_OPTS_KC_HEAP!"
set "JAVA_OPTS=!JAVA_OPTS! !JAVA_OPTS_KC_HEAP!"
)
@REM See also https://github.com/wildfly/wildfly-core/blob/7e5624cf92ebe4b64a4793a8c0b2a340c0d6d363/core-feature-pack/common/src/main/resources/content/bin/common.sh#L57-L60
if not "x%JAVA_ADD_OPENS%" == "x" (
echo "JAVA_ADD_OPENS already set in environment; overriding default settings"
echo "JAVA_ADD_OPENS already set in environment; overriding default settings"
) else (
set "JAVA_ADD_OPENS=--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED"
set "JAVA_ADD_OPENS=--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED"
)
set "JAVA_OPTS=%JAVA_OPTS% %JAVA_ADD_OPENS%"
@REM Set the default locale for the JVM to English to prevent locale-specific character variations
if not "x%JAVA_LOCALE%" == "x" (
echo "JAVA_LOCALE already set in environment; overriding default settings"
echo "JAVA_LOCALE already set in environment; overriding default settings"
) else (
set "JAVA_LOCALE=-Duser.language=en -Duser.country=US"
set "JAVA_LOCALE=-Duser.language=en -Duser.country=US"
)
set "JAVA_OPTS=%JAVA_OPTS% %JAVA_LOCALE%"
if not "x%JAVA_OPTS_APPEND%" == "x" (
echo "Appending additional Java properties to JAVA_OPTS"
set JAVA_OPTS=%JAVA_OPTS% %JAVA_OPTS_APPEND%
echo "Appending additional Java properties to JAVA_OPTS"
set JAVA_OPTS=%JAVA_OPTS% %JAVA_OPTS_APPEND%
)
if NOT "x%DEBUG%" == "x" (
set DEBUG_MODE=%DEBUG%
set DEBUG_MODE=%DEBUG%
)
if NOT "x%DEBUG_PORT%" == "x" (
set DEBUG_PORT_VAR=%DEBUG_PORT%
set DEBUG_PORT_VAR=%DEBUG_PORT%
)
if NOT "x%DEBUG_SUSPEND%" == "x" (
set DEBUG_SUSPEND_VAR=%DEBUG_SUSPEND%
set DEBUG_SUSPEND_VAR=%DEBUG_SUSPEND%
)
rem Set debug settings if not already set
if "%DEBUG_MODE%" == "true" (
echo "%JAVA_OPTS%" | findstr /I "\-agentlib:jdwp" > nul
if errorlevel == 1 (
set JAVA_OPTS=%JAVA_OPTS% -agentlib:jdwp=transport=dt_socket,address=%DEBUG_PORT_VAR%,server=y,suspend=%DEBUG_SUSPEND_VAR%
) else (
echo Debug already enabled in JAVA_OPTS, ignoring --debug argument
)
echo "%JAVA_OPTS%" | findstr /I "\-agentlib:jdwp" > nul
if errorlevel == 1 (
set JAVA_OPTS=%JAVA_OPTS% -agentlib:jdwp=transport=dt_socket,address=%DEBUG_ADDRESS%,server=y,suspend=%DEBUG_SUSPEND_VAR%
) else (
echo Debug already enabled in JAVA_OPTS, ignoring --debug argument
)
)
rem Setup Keycloak specific properties
set JAVA_OPTS=-Dprogram.name=%PROGNAME% %JAVA_OPTS%
if "x%JAVA%" == "x" (
if "x%JAVA_HOME%" == "x" (
set JAVA=java
echo JAVA_HOME is not set. Unexpected results may occur. 1>&2
echo Set JAVA_HOME to the directory of your local JDK to avoid this message. 1>&2
) else (
if not exist "%JAVA_HOME%" (
echo JAVA_HOME "%JAVA_HOME%" path doesn't exist 1>&2
goto END
if "x%JAVA_HOME%" == "x" (
set JAVA=java
echo JAVA_HOME is not set. Unexpected results may occur. 1>&2
echo Set JAVA_HOME to the directory of your local JDK to avoid this message. 1>&2
) else (
if not exist "%JAVA_HOME%\bin\java.exe" (
echo "%JAVA_HOME%\bin\java.exe" does not exist 1>&2
if not exist "%JAVA_HOME%" (
echo JAVA_HOME "%JAVA_HOME%" path doesn't exist 1>&2
goto END
)
set "JAVA=%JAVA_HOME%\bin\java"
) else (
if not exist "%JAVA_HOME%\bin\java.exe" (
echo "%JAVA_HOME%\bin\java.exe" does not exist 1>&2
goto END
)
set "JAVA=%JAVA_HOME%\bin\java"
)
)
)
@ -196,8 +205,8 @@ if not errorlevel == 1 (
)
if "%PRINT_ENV%" == "true" (
echo Using JAVA_OPTS: !JAVA_OPTS!
echo Using JAVA_RUN_OPTS: !JAVA_RUN_OPTS!
echo Using JAVA_OPTS: !JAVA_OPTS!
echo Using JAVA_RUN_OPTS: !JAVA_RUN_OPTS!
)
set START_SERVER=true

View File

@ -44,6 +44,7 @@ CLASSPATH_OPTS="'$(abs_path "../lib/quarkus-run.jar")'"
DEBUG_MODE="${DEBUG:-false}"
DEBUG_PORT="${DEBUG_PORT:-8787}"
DEBUG_SUSPEND="${DEBUG_SUSPEND:-n}"
DEBUG_ADDRESS="0.0.0.0:$DEBUG_PORT"
esceval() {
printf '%s\n' "$1" | sed "s/'/'\\\\''/g; 1 s/^/'/; $ s/$/'/"
@ -55,9 +56,20 @@ do
case "$1" in
--debug)
DEBUG_MODE=true
if [ -n "$2" ] && expr "$2" : '[0-9]\{0,\}$' >/dev/null; then
DEBUG_PORT=$2
shift
if [ -n "$2" ]; then
# Plain port
if echo "$2" | grep -Eq '^[0-9]+$'; then
DEBUG_ADDRESS="0.0.0.0:$2"
shift
# IPv4 or bracketed IPv6 with optional port
elif echo "$2" | grep -Eq '^(([0-9.]+)|(\[[0-9A-Fa-f:]+\]))'; then
if echo "$2" | grep -Eq ':[0-9]+$'; then
DEBUG_ADDRESS="$2"
else
DEBUG_ADDRESS="$2:$DEBUG_PORT"
fi
shift
fi
fi
;;
--)
@ -142,7 +154,7 @@ fi
if [ "$DEBUG_MODE" = "true" ]; then
DEBUG_OPT="$(echo "$JAVA_OPTS" | $GREP "\-agentlib:jdwp")"
if [ -z "$DEBUG_OPT" ]; then
JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=$DEBUG_SUSPEND"
JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_ADDRESS,server=y,suspend=$DEBUG_SUSPEND"
else
echo "Debug already enabled in JAVA_OPTS, ignoring --debug argument"
fi
@ -152,7 +164,7 @@ esceval_args() {
while IFS= read -r entry; do
result="$result $(esceval "$entry")"
done
echo $result
echo "$result"
}
JAVA_RUN_OPTS=$(echo "$JAVA_OPTS" | xargs printf '%s\n' | esceval_args)
@ -166,8 +178,8 @@ if [ "$PRINT_ENV" = "true" ]; then
fi
if [ "$PRE_BUILD" = "true" ]; then
eval "'$JAVA'" -Dkc.config.build-and-exit=true $JAVA_RUN_OPTS || exit $?
eval "'$JAVA'" -Dkc.config.build-and-exit=true "$JAVA_RUN_OPTS" || exit $?
JAVA_RUN_OPTS="-Dkc.config.built=true $JAVA_RUN_OPTS"
fi
eval exec "'$JAVA'" $JAVA_RUN_OPTS
eval exec "'$JAVA'" "$JAVA_RUN_OPTS"