diff --git a/jetty-home/src/main/resources/bin/jetty.sh b/jetty-home/src/main/resources/bin/jetty.sh
index ebcf0f43296c..de54453f0c64 100755
--- a/jetty-home/src/main/resources/bin/jetty.sh
+++ b/jetty-home/src/main/resources/bin/jetty.sh
@@ -495,13 +495,10 @@ case "$ACTION" in
# FIXME: Broken solution: wordsplitting, pathname expansion, arbitrary command execution, etc.
su - "$JETTY_USER" $SU_SHELL -c "
cd \"$JETTY_BASE\"
- echo ${RUN_ARGS[*]} start-log-file=\"$JETTY_START_LOG\" | xargs ${JAVA} > /dev/null &
- disown \$!
- echo \$! > \"$JETTY_PID\""
+ echo ${RUN_ARGS[*]} --pid-file=\"$JETTY_PID\" start-log-file=\"$JETTY_START_LOG\" | xargs ${JAVA} > /dev/null &
+ "
else
- echo ${RUN_ARGS[*]} | xargs ${JAVA} > /dev/null &
- disown $!
- echo $! > "$JETTY_PID"
+ echo ${RUN_ARGS[*]} | xargs ${JAVA} --pid-file="$JETTY_PID" > /dev/null &
fi
fi
diff --git a/jetty-home/src/main/resources/etc/jetty-pid.xml b/jetty-home/src/main/resources/etc/jetty-pid.xml
new file mode 100644
index 000000000000..573953cdd27f
--- /dev/null
+++ b/jetty-home/src/main/resources/etc/jetty-pid.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
index b1554fa0237f..d1e6e42e6237 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
@@ -202,6 +202,7 @@ public class StartArgs
private boolean help = false;
private boolean stopCommand = false;
+ private String pidFile = null;
private List listModules = null;
private List showModules = null;
private boolean listClasspath = false;
@@ -919,6 +920,11 @@ public String getModuleGraphFilename()
return moduleGraphFilename;
}
+ public String getPidFile()
+ {
+ return pidFile;
+ }
+
public Props getProperties()
{
return properties;
@@ -1169,6 +1175,13 @@ public void parse(final String rawarg, String source)
return;
}
+ if (arg.startsWith("--pid-file="))
+ {
+ setProperty("jetty.pid.file", pidFile, source);
+ xmlRefs.add("etc/jetty-pid.xml");
+ return;
+ }
+
if (arg.startsWith("--download="))
{
addFile(null, Props.getValue(arg));
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/PidFileLifeCycleListener.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/PidFileLifeCycleListener.java
new file mode 100644
index 000000000000..76e3ca66d8c5
--- /dev/null
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/PidFileLifeCycleListener.java
@@ -0,0 +1,73 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2023 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.util.component;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PidFileLifeCycleListener implements LifeCycle.Listener
+{
+ private static final Logger LOG = LoggerFactory.getLogger(PidFileLifeCycleListener.class);
+
+ private final Path pidFile;
+
+ public PidFileLifeCycleListener(String filename)
+ {
+ pidFile = Paths.get(filename);
+ }
+
+ @Override
+ public void lifeCycleStarting(LifeCycle event)
+ {
+ long pid = ProcessHandle.current().pid();
+ try
+ {
+ Files.writeString(pidFile, Long.toString(pid), StandardCharsets.UTF_8);
+ }
+ catch (IOException e)
+ {
+ LOG.warn("Unable to create pidFile: {}", pidFile, e);
+ }
+ }
+
+ @Override
+ public void lifeCycleFailure(LifeCycle event, Throwable cause)
+ {
+ removePid();
+ }
+
+ @Override
+ public void lifeCycleStopped(LifeCycle event)
+ {
+ removePid();
+ }
+
+ private void removePid()
+ {
+ try
+ {
+ Files.deleteIfExists(pidFile);
+ }
+ catch (IOException e)
+ {
+ LOG.warn("Unable to remove pidFile: {}", pidFile, e);
+ }
+ }
+}