sage-server.service
[Service]
ExecStart=/usr/local/jdk-21.0.2+13/bin/java -jar /home/freedom/local/sage-app*.jar
When I run systemctl status sage-server
, it fails.
Error: Unable to access jarfile /home/freedom/local/sage-app*.jar
But if I run /usr/local/jdk-21.0.2+13/bin/java -jar /home/freedom/local/sage-app*.jar
directly at the terminal prompt, it is successful.
Linux version: Debian 12
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
ExecStart doen’t permit you to use shell features … unless you ExecStart a shell.
ExecStart=/bin/sh -c '/usr/local/jdk-21.0.2+13/bin/java -jar /home/freedom/local/sage-app*.jar'
Depending on your use case, it might be better to write the specific file name instead of a wildcard if you can. But if you can’t control the precise file name, this is robust in the sense that it will find one if there is one; but also brittle in that it will find and attempt to pass all of them if there is more than one, probably in precisely the opposite order from what you would likely prefer (they are sorted alphabetically, so typically oldest first in many version numbering schemes).
If you would like to only pass in the last of the matches, maybe something like
for jar in /home/freedom/local/sage-app*.jar; do
if ! [ -f "$jar" ]; then
echo "$0: no match on $jar" >&2
exit 123
fi
done
exec /usr/local/jdk-21.0.2+13/bin/java "$jar"
In so many words, this loops over the matches; after the loop, the last one will be left in the loop variable.
While you can put arbitrarily complex code in sh -c
(you’ll need to replace newlines with semicolons if you want it all on one line, except after do
and then
) it’s probably better at this point to put the code in a file, add a #!/bin/sh
shebang at the top, chmod +x
the file, and just put the filename after ExecStart=
1