diff --git a/defaults/yacy.init b/defaults/yacy.init
index 2aa3109e3..357dd83ca 100644
--- a/defaults/yacy.init
+++ b/defaults/yacy.init
@@ -13,6 +13,9 @@ port = 8090
# optinal ssl port (https port) the server should bind to
port.ssl = 8443
+# port to listen for a shutdown signal ( -1 = disable use of a shutdown port, 8005 = recommended default )
+port.shutdown = -1
+
# prefix for new default peer names
peernameprefix=_anon
diff --git a/htroot/SettingsAck_p.html b/htroot/SettingsAck_p.html
index cb0c346d1..04c5be21d 100644
--- a/htroot/SettingsAck_p.html
+++ b/htroot/SettingsAck_p.html
@@ -194,7 +194,20 @@
::
Debug/Analysis settings have been saved.
::
-
Referrer policy settings have been saved.
+
Referrer policy settings have been saved.
+ ::
+
The ports are now configured as follows (active on next start).
+
+
+
HTTP port
#[port]#
+
+
+
HTTPS port
#[port.ssl]#
+
+
+
Shutdown port
#[port.shutdown]#
+
+
#(/info)#
#(needsRestart)#
diff --git a/htroot/SettingsAck_p.java b/htroot/SettingsAck_p.java
index 2ee5608bc..2380f5882 100644
--- a/htroot/SettingsAck_p.java
+++ b/htroot/SettingsAck_p.java
@@ -531,6 +531,22 @@ public class SettingsAck_p {
return prop;
}
+ // server port settings
+ if (post.containsKey("serverports")) {
+ int port = post.getInt("port", 8090);
+ if (port > 0) env.setConfig(SwitchboardConstants.SERVER_PORT, port);
+ int portssl = post.getInt("port.ssl", 8443);
+ if (portssl > 0) env.setConfig(SwitchboardConstants.SERVER_SSLPORT, portssl);
+ int portshutdown = post.getInt("port.shutdown", -1);
+ env.setConfig(SwitchboardConstants.SERVER_SHUTDOWNPORT, portshutdown);
+ prop.put("info_port", port);
+ prop.put("info_port.ssl", portssl);
+ prop.put("info_port.shutdown", portshutdown);
+ prop.put("needsRestart_referer", "Settings_p.html?page=ServerAccess");
+ prop.put("info", "36");
+ return prop;
+ }
+
// change https port
if (post.containsKey("port.ssl")) {
diff --git a/htroot/Settings_ServerAccess.inc b/htroot/Settings_ServerAccess.inc
index a9476e8bb..82c004cd7 100644
--- a/htroot/Settings_ServerAccess.inc
+++ b/htroot/Settings_ServerAccess.inc
@@ -59,4 +59,28 @@
+
+
+
\ No newline at end of file
diff --git a/htroot/Settings_p.java b/htroot/Settings_p.java
index 39b05bc72..5630daa87 100644
--- a/htroot/Settings_p.java
+++ b/htroot/Settings_p.java
@@ -198,8 +198,9 @@ public final class Settings_p {
prop.putHTML("crawler.file.maxFileSize",sb.getConfig("crawler.file.maxFileSize", "-1"));
// http server info
- prop.put("server.https",sb.getConfigBool("server.https", false));
- prop.put("server.https_port.ssl", sb.getConfig("port.ssl","8443"));
+ prop.put("server.https", sb.getConfigBool("server.https", false));
+ prop.put("server.https_port.ssl", sb.getConfig(SwitchboardConstants.SERVER_SSLPORT,"8443"));
+ prop.put("port.shutdown", sb.getConfig(SwitchboardConstants.SERVER_SHUTDOWNPORT, "-1"));
// debug/analysis
prop.put("solrBinaryResponseChecked", env.getConfigBool(SwitchboardConstants.REMOTE_SOLR_BINARY_RESPONSE_ENABLED,
diff --git a/source/net/yacy/search/Switchboard.java b/source/net/yacy/search/Switchboard.java
index 13fedf146..a5ad92f2b 100644
--- a/source/net/yacy/search/Switchboard.java
+++ b/source/net/yacy/search/Switchboard.java
@@ -47,9 +47,13 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
+import java.net.InetAddress;
import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
@@ -208,6 +212,7 @@ import net.yacy.search.ranking.RankingProfile;
import net.yacy.search.schema.CollectionConfiguration;
import net.yacy.search.schema.CollectionSchema;
import net.yacy.search.schema.WebgraphConfiguration;
+import net.yacy.server.serverCore;
import net.yacy.server.serverSwitch;
import net.yacy.server.http.RobotsTxtConfig;
import net.yacy.utils.CryptoLib;
@@ -4036,7 +4041,71 @@ public final class Switchboard extends serverSwitch {
return this.terminate;
}
+ /**
+ * Wait until the shutdown semaphore is released.
+ * Optionally if config defines a shutdown port a thread is initalized, to
+ * listen on a defined shutdown port on the local loopback address. If a
+ * connection is made to the shutdown port an a text containig "shutdown"
+ * command, a shutdown is initiated.
+ * @return
+ * @throws InterruptedException
+ */
public boolean waitForShutdown() throws InterruptedException {
+ final int shutdownPort;
+ if ((shutdownPort = this.getConfigInt(SwitchboardConstants.SERVER_SHUTDOWNPORT, 0)) > 0) {
+ // init thread to listen to a shutdown port - to receive a shutdown signal
+ Thread shutdownThread = new Thread() {
+ @Override
+ public void run() {
+ ServerSocket ss = null;
+ try {
+
+ shutdownloop: while (true) {
+ ss = new ServerSocket(shutdownPort, 0, InetAddress.getLoopbackAddress());
+ Socket shSocket = ss.accept();
+
+ InputStream in = shSocket.getInputStream();
+ BufferedReader inreader = new BufferedReader(new InputStreamReader(in));
+ String cmd = inreader.readLine(); // read a input line to check for command shutdown
+
+ // check for shutdown command, accept e.g. http://localhost:8009/shutdown connect with input line "GET /shutdown HTTP/1.1"
+ if (cmd != null && !cmd.isEmpty()) {
+ if (cmd.contains("shutdown")) {
+ if (cmd.contains("HTTP")) { // write a min. http response
+ OutputStream out = shSocket.getOutputStream();
+ out.write(UTF8.getBytes("HTTP/1.1 200 OK"));
+ out.write(serverCore.CRLF);
+ out.close();
+ }
+ ss.close();
+ terminate("shutdown signal received on shutdown port");
+ } else if (cmd.contains("restart")) {
+ if (cmd.contains("HTTP")) { // write a min. http response
+ OutputStream out = shSocket.getOutputStream();
+ out.write(UTF8.getBytes("HTTP/1.1 200 OK"));
+ out.write(serverCore.CRLF);
+ out.close();
+ }
+ ss.close();
+ yacyRelease.restart();
+ }
+ break shutdownloop; // important to get out of the loop
+ }
+ ss.close(); // we don't want to accept any additional input (abort/disconnect if not expected input)
+ }
+ } catch (IOException ex) {
+ } finally {
+ if (ss != null) {
+ try {
+ ss.close();
+ } catch (IOException ex) { }
+ }
+ }
+ }
+ };
+ shutdownThread.start();
+ }
+
this.shutdownSync.acquire();
return this.terminate;
}
diff --git a/source/net/yacy/search/SwitchboardConstants.java b/source/net/yacy/search/SwitchboardConstants.java
index 8e1892006..3df5c1a55 100644
--- a/source/net/yacy/search/SwitchboardConstants.java
+++ b/source/net/yacy/search/SwitchboardConstants.java
@@ -57,6 +57,7 @@ public final class SwitchboardConstants {
// server settings
public static final String SERVER_PORT = "port"; // port for the http server
public static final String SERVER_SSLPORT = "port.ssl"; // port for https
+ public static final String SERVER_SHUTDOWNPORT = "port.shutdown"; // local port to listen for a shutdown signal (0 <= disabled)
public static final String SERVER_STATICIP = "staticIP"; // static IP of http server
public static final String PUBLIC_SEARCHPAGE = "publicSearchpage";
diff --git a/source/net/yacy/server/serverSwitch.java b/source/net/yacy/server/serverSwitch.java
index fbcc982e5..83e158d1f 100644
--- a/source/net/yacy/server/serverSwitch.java
+++ b/source/net/yacy/server/serverSwitch.java
@@ -157,7 +157,7 @@ public class serverSwitch {
@Deprecated
public String myPublicIP() {
// if a static IP was configured, we have to return it here ...
- final String staticIP = getConfig("staticIP", "");
+ final String staticIP = getConfig(SwitchboardConstants.SERVER_STATICIP, "");
if (staticIP.length() > 0)
return staticIP;
@@ -176,7 +176,7 @@ public class serverSwitch {
*/
public Set myPublicIPs() {
// if a static IP was configured, we have to return it here ...
- final String staticIP = getConfig("staticIP", "");
+ final String staticIP = getConfig(SwitchboardConstants.SERVER_STATICIP, "");
if (staticIP.length() > 0) {
HashSet h = new HashSet<>();
h.add(staticIP);
@@ -254,7 +254,7 @@ public class serverSwitch {
if(localPort != null) {
return localPort;
}
- return getConfigInt("port", 8090);
+ return getConfigInt(SwitchboardConstants.SERVER_PORT, 8090);
}
// a logger for this switchboard