From: Mathieu Baudier Date: Tue, 5 Mar 2024 09:14:58 +0000 (+0100) Subject: Refactor Argeo init X-Git-Tag: v2.3.6~10 X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-freed.git;a=commitdiff_plain;h=a4bbce69890aa92021cf5140338e22f38b8d7d9f Refactor Argeo init --- diff --git a/etc/argeo/user/slc/argeo.ini b/etc/argeo/user/slc/argeo.ini index 45c47c9..0f5be10 100644 --- a/etc/argeo/user/slc/argeo.ini +++ b/etc/argeo/user/slc/argeo.ini @@ -1,9 +1,10 @@ ## OSGi system extensions +# giving additional access to Argeo Init and Sun Misc org.osgi.framework.system.packages.extra=\ -org.argeo.init,\ -org.argeo.init.a2,\ -org.argeo.init.osgi,\ +org.argeo.api.init,\ +org.argeo.api.a2,\ +sun.misc,\ sun.security.util,\ sun.security.internal.spec,\ sun.security.provider,\ diff --git a/etc/argeo/user/slc/debug.ini b/etc/argeo/user/slc/debug.ini index 0ab492a..82da55a 100644 --- a/etc/argeo/user/slc/debug.ini +++ b/etc/argeo/user/slc/debug.ini @@ -1,2 +1,2 @@ -osgi.console=2023 +osgi.console=localhost:2023 osgi.clean=true \ No newline at end of file diff --git a/sjbin/src/freed-pid1.java b/sjbin/src/freed-pid1.java deleted file mode 100644 index 446cc0e..0000000 --- a/sjbin/src/freed-pid1.java +++ /dev/null @@ -1,309 +0,0 @@ -//#! /usr/bin/java --source 17 @/usr/local/etc/freed/pid1/jvm.args - -import static java.lang.System.Logger.Level.DEBUG; -import static java.lang.System.Logger.Level.ERROR; -import static java.lang.System.Logger.Level.INFO; -import static java.lang.System.Logger.Level.WARNING; - -import java.io.Console; -import java.io.IOException; -import java.lang.System.Logger; -import java.lang.management.ManagementFactory; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.argeo.init.Service; - -import sun.misc.Signal; - -/** A minimalistic Linux init process. */ -class FreedPid1 { - final static AtomicInteger runLevel = new AtomicInteger(-1); - - private final static Logger logger = System.getLogger(FreedPid1.class.getName()); - - private final static List initDServices = Collections.synchronizedList(new ArrayList<>()); - - public static void main(String... args) { - try { - final long pid = ProcessHandle.current().pid(); - Signal.handle(new Signal("TERM"), (signal) -> { - System.out.println("SIGTERM caught"); - System.exit(0); - }); - Signal.handle(new Signal("INT"), (signal) -> { - System.out.println("SIGINT caught"); - System.exit(0); - }); - Signal.handle(new Signal("HUP"), (signal) -> { - System.out.println("SIGHUP caught"); - System.exit(0); - }); - - boolean isSystemInit = pid == 1 || pid == 2; - - if (isSystemInit && args.length > 0 && ("1".equals(args[0]) // - || "single".equals(args[0]) // - || "emergency".equals(args[0]))) { - runLevel.set(1); - for (Object key : new TreeMap<>(System.getProperties()).keySet()) { - System.out.println(key + "=" + System.getProperty(key.toString())); - } - System.out.println("Single user mode"); - System.out.flush(); - ProcessBuilder pb = new ProcessBuilder("/bin/bash"); - pb.redirectError(ProcessBuilder.Redirect.INHERIT); - pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); - pb.redirectInput(ProcessBuilder.Redirect.INHERIT); - Process singleUserShell = pb.start(); - singleUserShell.waitFor(); - } else { - if (args.length == 0) - runLevel.set(5); - else - runLevel.set(Integer.parseInt(args[0])); - - if (runLevel.get() == 0) {// shutting down the whole system - if (!isSystemInit) { - logger.log(INFO, "Shutting down system..."); - shutdown(false); - System.exit(0); - } else { - logger.log(ERROR, "Cannot start at run level " + runLevel.get()); - System.exit(1); - } - } else if (runLevel.get() == 6) {// reboot the whole system - if (!isSystemInit) { - logger.log(INFO, "Rebooting the system..."); - shutdown(true); - } else { - logger.log(ERROR, "Cannot start at run level " + runLevel.get()); - System.exit(1); - } - } - - logger.log(INFO, "FREEd Init daemon starting with pid " + pid + " after " - + ManagementFactory.getRuntimeMXBean().getUptime() + " ms"); - // hostname - String hostname = Files.readString(Paths.get("/etc/hostname")); - new ProcessBuilder("/usr/bin/hostname", hostname).start(); - logger.log(DEBUG, "Set hostname to " + hostname); - // networking - initSysctl(); - startInitDService("networking", true); -// Thread.sleep(3000);// leave some time for network to start up - if (!waitForNetwork(10 * 1000)) - logger.log(ERROR, "No network available"); - - // OpenSSH - // TODO make it coherent with Java sshd - startInitDService("ssh", true); - - // NSS services - startInitDService("nslcd", false);// Note: nslcd fails to stop - - // login prompt - Service.addPostStart(() -> new LoginThread().start()); - - // init Argeo CMS - logger.log(INFO, "FREEd Init daemon starting Argeo Init after " - + ManagementFactory.getRuntimeMXBean().getUptime() + " ms"); - Service.main(args); - } - } catch (Throwable e) { - logger.log(ERROR, "Unexpected exception in free-pid1 init, shutting down... ", e); - System.exit(1); - } finally { - stopInitDServices(); - } - } - - static void initSysctl() { - try { - Path sysctlD = Paths.get("/etc/sysctl.d/"); - for (Path conf : Files.newDirectoryStream(sysctlD, "*.conf")) { - try { - new ProcessBuilder("/usr/sbin/sysctl", "-p", conf.toString()).start(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - static void startInitDService(String serviceName, boolean stopOnShutdown) { - Path serviceInit = Paths.get("/etc/init.d/", serviceName); - if (Files.exists(serviceInit)) - try { - int exitCode = new ProcessBuilder(serviceInit.toString(), "start").start().waitFor(); - if (exitCode != 0) - logger.log(ERROR, "Service " + serviceName + " dit not stop properly"); - else - logger.log(DEBUG, "Service " + serviceName + " started"); - if (stopOnShutdown) - initDServices.add(serviceName); -// Runtime.getRuntime().addShutdownHook(new Thread(() -> { -// try { -// new ProcessBuilder(serviceInit.toString(), "stop").start().waitFor(); -// } catch (IOException | InterruptedException e) { -// e.printStackTrace(); -// } -// }, "FREEd stop service " + serviceName)); - } catch (IOException | InterruptedException e) { - e.printStackTrace(); - } - else - logger.log(WARNING, "Service " + serviceName + " not found and therefore not started"); - } - - static boolean waitForNetwork(long timeout) { - long begin = System.currentTimeMillis(); - long duration = 0; - boolean networkAvailable = false; - try { - networkAvailable: while (!networkAvailable) { - duration = System.currentTimeMillis() - begin; - if (duration > timeout) - break networkAvailable; - Enumeration netInterfaces = null; - try { - netInterfaces = NetworkInterface.getNetworkInterfaces(); - } catch (SocketException e) { - throw new IllegalStateException("Cannot list network interfaces", e); - } - if (netInterfaces != null) { - while (netInterfaces.hasMoreElements()) { - NetworkInterface netInterface = netInterfaces.nextElement(); - logger.log(DEBUG, "Interface:" + netInterface); - for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { - InetAddress inetAddr = addr.getAddress(); - logger.log(DEBUG, " addr: " + inetAddr); - if (!inetAddr.isLoopbackAddress() && !inetAddr.isLinkLocalAddress()) { - try { - if (inetAddr.isReachable((int) timeout)) { - networkAvailable = true; - duration = System.currentTimeMillis() - begin; - logger.log(DEBUG, - "Network available after " + duration + " ms. IP: " + inetAddr); - break networkAvailable; - } - } catch (IOException e) { - logger.log(ERROR, "Cannot check whether " + inetAddr + " is reachable", e); - } - } - } - } - } else { - throw new IllegalStateException("No network interface has been found"); - } - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // silent - } - } - } catch (Exception e) { - logger.log(ERROR, "Cannot check whether network is available", e); - } - return networkAvailable; - } - - static void shutdown(boolean reboot) { - try { - stopInitDServices(); - Path sysrqP = Paths.get("/proc/sys/kernel/sysrq"); - Files.writeString(sysrqP, "1"); - Path sysrqTriggerP = Paths.get("/proc/sysrq-trigger"); - Files.writeString(sysrqTriggerP, "e");// send SIGTERM to all processes - // Files.writeString(sysrqTriggerP, "i");// send SIGKILL to all processes - Files.writeString(sysrqTriggerP, "e");// flush data to disk - Files.writeString(sysrqTriggerP, "u");// unmount - if (reboot) - Files.writeString(sysrqTriggerP, "b"); - else - Files.writeString(sysrqTriggerP, "o"); - } catch (IOException e) { - logger.log(ERROR, "Cannot shut down system", e); - } - } - - static void stopInitDServices() { - for (int i = initDServices.size() - 1; i >= 0; i--) { - String serviceName = initDServices.get(i); - Path serviceInit = Paths.get("/etc/init.d/", serviceName); - try { - int exitCode = new ProcessBuilder(serviceInit.toString(), "stop").start().waitFor(); - if (exitCode != 0) - logger.log(ERROR, "Service " + serviceName + " dit not stop properly"); - } catch (InterruptedException | IOException e) { - logger.log(ERROR, "Cannot stop service " + serviceName, e); - } - } - } - - /** A thread watching the login prompt. */ - static class LoginThread extends Thread { - private boolean systemShuttingDown = false; - private Process process = null; - - public LoginThread() { - super("FREEd login prompt"); - setDaemon(true); - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - systemShuttingDown = true; - if (process != null) - process.destroy(); - })); - } - - @Override - public void run() { - boolean getty = true; - prompt: while (!systemShuttingDown) { - try { - if (getty) { - ProcessBuilder pb = new ProcessBuilder("/usr/sbin/getty", "38400", "tty2"); - process = pb.start(); - } else { - Console console = System.console(); - console.readLine(); // type return once to activate login prompt - console.printf("login: "); - String username = console.readLine(); - username = username.trim(); - if ("".equals(username)) - continue prompt; - ProcessBuilder pb = new ProcessBuilder("su", "--login", username); - pb.redirectError(ProcessBuilder.Redirect.INHERIT); - pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); - pb.redirectInput(ProcessBuilder.Redirect.INHERIT); - process = pb.start(); - } - Runtime.getRuntime().addShutdownHook(new Thread(() -> process.destroy())); - try { - process.waitFor(); - } catch (InterruptedException e) { - process.destroy(); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - process = null; - } - } - } - - } -} diff --git a/sjbin/src/freed-register.java b/sjbin/src/freed-register.java new file mode 100644 index 0000000..37d63c2 --- /dev/null +++ b/sjbin/src/freed-register.java @@ -0,0 +1,8 @@ +//#! /usr/bin/java --source 17 @/usr/local/etc/freed/pid1/jvm.args + +/** Register to a FREEd-compatible infrastructure. */ +class FreedPid1 { + + public static void main(String... args) { + } +} diff --git a/usr/lib/systemd/system/argeo@.service b/usr/lib/systemd/system/argeo@.service index b940216..f080622 100644 --- a/usr/lib/systemd/system/argeo@.service +++ b/usr/lib/systemd/system/argeo@.service @@ -29,7 +29,7 @@ ExecStart=java \ @/etc/argeo.d/jvm.args \ @${CONFIGURATION_DIRECTORY}/jvm.args \ @/usr/share/argeo/jvm.args \ -org.argeo.init.Service +org.argeo.init.ServiceMain # Exit codes of the JVM when SIGTERM or SIGINT have been caught: SuccessExitStatus=143 130 diff --git a/usr/lib/systemd/user/argeo.service b/usr/lib/systemd/user/argeo.service index 8534a94..ba6f78d 100644 --- a/usr/lib/systemd/user/argeo.service +++ b/usr/lib/systemd/user/argeo.service @@ -21,7 +21,7 @@ ExecStart=java \ @etc/argeo/user/jvm.args \ @${CONFIGURATION_DIRECTORY}/jvm.args \ @lib/argeo/jvm.args \ -org.argeo.init.RuntimeManager \ +org.argeo.init.RuntimeManagerMain \ etc/argeo/user/slc # Exit codes of the JVM when SIGTERM or SIGINT have been caught: diff --git a/usr/lib/systemd/user/argeo@.service b/usr/lib/systemd/user/argeo@.service index 3e378b8..04b77b1 100644 --- a/usr/lib/systemd/user/argeo@.service +++ b/usr/lib/systemd/user/argeo@.service @@ -24,7 +24,7 @@ ExecStart=java \ @/etc/argeo.user.d/jvm.args \ @/etc/argeo.user.d/%I/jvm.args \ @/usr/share/argeo/jvm.args \ -org.argeo.init.Service +org.argeo.init.ServiceMain # Exit codes of the JVM when SIGTERM or SIGINT have been caught: SuccessExitStatus=143 130