SDKMAN has predefined post installation hooks but there doesn't seem any way to customize them or add your own. I didn't want to create a new wrapper tool like @PeterMue because it'd cause cognitive load and also the footgun of users forgetting to run that, so my solution was to hook into the shell's prompt mechanism. I installed starship
(https://starship.rs) and put the eval "$(starship init <shell>)"
below SDKMan, and in ~/.config/starship.toml
I defined a section for a custom command which will be run during prompt generation:
[custom.java-cacerts]
when = true
shell = "sh"
command = """
set -xe
[ -f /etc/ssl/certs/java/cacerts ]
ALL_CACERTS=$(find -P "$SDKMAN_DIR/candidates/java" -name cacerts -type f | grep .)
echo "[java: symlinking cacerts]"
for cacerts in $ALL_CACERTS; do
mv "$cacerts" "$cacerts.original"
ln -s /etc/ssl/certs/java/cacerts "$cacerts"
done 2>&1
"""
Explanation:
set -xe
sets the e
flag (exit when any command errors) and the x
flag (log commands to stderr
)
- Since
e
flag is set, we can skip the if
clause and write the condition at the top. If it fails, the script will short circuit
find -P
doesn't follow symlinks, so the current
symlink is ignored. -type f
to only find cacerts
which are regular files (no symlinks)
find
always returns success even when no match was found. Piping that into grep .
matches anything and causes a non-zero status when there is no input so the script will stop
set -x
writes everything to stderr
, but starship
only captures stdout
and ignores stderr, so I use 2>&1
on the for
loop to print those 2 commands to inform the user.
This runs very fast and on my machine the prompt delay is almost not noticeable. Also using find
rather than a predefined path on $JDK/lib/security/cacerts
is more backward compatible as for Java 8 the cacerts
is under $JDK/jre/lib/security/cacerts
.