Compare commits
	
		
			3 Commits
		
	
	
		
			0594a64812
			...
			947bccb6da
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 947bccb6da | |||
| 998357385e | |||
| 7e2d4ca1a4 | 
@@ -0,0 +1,152 @@
 | 
				
			|||||||
 | 
					package name.nathanmcrae.numbersstation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.leakyabstractions.result.api.Result;
 | 
				
			||||||
 | 
					import com.leakyabstractions.result.core.Results;
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.io.OutputStreamWriter;
 | 
				
			||||||
 | 
					import java.io.Writer;
 | 
				
			||||||
 | 
					import java.nio.charset.StandardCharsets;
 | 
				
			||||||
 | 
					import java.nio.file.Files;
 | 
				
			||||||
 | 
					import java.nio.file.Path;
 | 
				
			||||||
 | 
					import java.nio.file.Paths;
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeUnit;
 | 
				
			||||||
 | 
					import java.util.logging.Level;
 | 
				
			||||||
 | 
					import java.util.logging.Logger;
 | 
				
			||||||
 | 
					import java.util.regex.Matcher;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					import javafx.util.Pair;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class LinuxScheduler {
 | 
				
			||||||
 | 
					    private static final Logger logger = Logger.getLogger(Main.class.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Result<Boolean, String> registerSchedule(StationSettings settings) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            String taskName = "numbers-station-main_" + settings.getName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // TODO: assume it's on the PATH
 | 
				
			||||||
 | 
					            Process listProcess = new ProcessBuilder("/usr/bin/crontab", "-l").start();
 | 
				
			||||||
 | 
					            if (!listProcess.waitFor(5, TimeUnit.SECONDS)) {
 | 
				
			||||||
 | 
					                String message = "Failed to query " + taskName + " task: process timed out";
 | 
				
			||||||
 | 
					                logger.log(Level.SEVERE, message);
 | 
				
			||||||
 | 
					                return Results.failure(message);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Pair<String, String> output = WindowsScheduler.captureProcessOutput(listProcess);
 | 
				
			||||||
 | 
					            if(listProcess.exitValue() != 0) {
 | 
				
			||||||
 | 
					                String message = "Failed to get user id. Exit code: " + listProcess.exitValue() + ". stdout: " + output.getKey() + "\n\tstderr: " + output.getValue();
 | 
				
			||||||
 | 
					                logger.log(Level.SEVERE, message);
 | 
				
			||||||
 | 
					                return Results.failure(message);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            String currentCrontab = output.getKey();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            String cronEntry = "# " + taskName + "\n" + cronExpression(settings) + "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Pattern pattern = Pattern.compile("# " + taskName + "\\n[^\\n]+\\n\\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Matcher matcher = pattern.matcher(currentCrontab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            StringBuilder sb = new StringBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (matcher.find()) {
 | 
				
			||||||
 | 
					                matcher.appendReplacement(sb, cronEntry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                boolean foundMultiple = false;
 | 
				
			||||||
 | 
					                while (matcher.find()) {
 | 
				
			||||||
 | 
					                    foundMultiple = true;
 | 
				
			||||||
 | 
					                    matcher.appendReplacement(sb, "");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                matcher.appendTail(sb);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                sb.append(currentCrontab);
 | 
				
			||||||
 | 
					                sb.append(cronEntry);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            String newCrontab = sb.toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // TODO: assume it's on the PATH
 | 
				
			||||||
 | 
					            Process addProcess = new ProcessBuilder("/usr/bin/crontab", "-").start();
 | 
				
			||||||
 | 
					            Writer w = new OutputStreamWriter(addProcess.getOutputStream(), "UTF-8");
 | 
				
			||||||
 | 
					            System.out.println(newCrontab);
 | 
				
			||||||
 | 
					            w.write(newCrontab);
 | 
				
			||||||
 | 
					            w.flush();
 | 
				
			||||||
 | 
					            w.close();
 | 
				
			||||||
 | 
					            if (!addProcess.waitFor(5, TimeUnit.SECONDS)) {
 | 
				
			||||||
 | 
					                String message = "Failed to register " + taskName + " task: process timed out";
 | 
				
			||||||
 | 
					                logger.log(Level.SEVERE, message);
 | 
				
			||||||
 | 
					                return Results.failure(message);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(addProcess.exitValue() != 0) {
 | 
				
			||||||
 | 
					                Pair<String, String> addOutput = WindowsScheduler.captureProcessOutput(addProcess);
 | 
				
			||||||
 | 
					                String message = "Failed to get user id. Exit code: " + addProcess.exitValue() + ". stdout: " + addOutput.getKey() + ". stderr: " + addOutput.getValue();
 | 
				
			||||||
 | 
					                logger.log(Level.SEVERE, message);
 | 
				
			||||||
 | 
					                return Results.failure(message);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (CronExpressionException | IOException | InterruptedException e) {
 | 
				
			||||||
 | 
					            String message = "Exception while registering schedule";
 | 
				
			||||||
 | 
					            logger.log(Level.SEVERE, message, e);
 | 
				
			||||||
 | 
					            return Results.failure(message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Path cronDPath = Paths.get("/etc/cron.d");
 | 
				
			||||||
 | 
					        // if (!Files.exists(cronDPath)) {
 | 
				
			||||||
 | 
					        //     String message =  "/etc/cron.d does not exist, cannot create cron entry. Select 'Manage schedule externally' and set up scheduling as desired.";
 | 
				
			||||||
 | 
					        //     logger.log(Level.SEVERE, message);
 | 
				
			||||||
 | 
					        //     return Results.failure(message);
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Path cronPath = cronDPath.resolve(settings.safeName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // try {
 | 
				
			||||||
 | 
					        //     Files.write(cronPath, cronEntry(settings).getBytes(StandardCharsets.UTF_8));
 | 
				
			||||||
 | 
					        // } catch (Exception e) {
 | 
				
			||||||
 | 
					        //     String message = "Failed to write cron file at '" + cronPath.toString() + "'";
 | 
				
			||||||
 | 
					        //     logger.log(Level.SEVERE, message, e);
 | 
				
			||||||
 | 
					        //     return Results.failure(message);
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Results.success(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  * * * * * {command to execute}
 | 
				
			||||||
 | 
					     *  | | | | |
 | 
				
			||||||
 | 
					     *  | | | | day of the week (0–6) (Sunday to Saturday;
 | 
				
			||||||
 | 
					     *  | | | month (1–12)             7 is also Sunday on some systems)
 | 
				
			||||||
 | 
					     *  | | day of the month (1–31)
 | 
				
			||||||
 | 
					     *  | hour (0–23)
 | 
				
			||||||
 | 
					     *  minute (0–59)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static String cronExpression(StationSettings settings) throws CronExpressionException {
 | 
				
			||||||
 | 
					        String minute = Integer.toString(settings.getScheduleStartTime().getMinute());
 | 
				
			||||||
 | 
					        String hour = Integer.toString(settings.getScheduleStartTime().getHour());
 | 
				
			||||||
 | 
					        String dayOfMonth = Integer.toString(settings.getScheduleStartDate().getDayOfMonth());
 | 
				
			||||||
 | 
					        String dayOfWeek = Integer.toString(settings.getScheduleStartDate().getDayOfMonth());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        String scheduleString = "";
 | 
				
			||||||
 | 
					        switch(settings.getMessagePeriod()) {
 | 
				
			||||||
 | 
					            case DAILY:
 | 
				
			||||||
 | 
					                scheduleString = minute + " " + hour + " * * *";
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case WEEKLY:
 | 
				
			||||||
 | 
					                scheduleString = minute + " " + hour + " * * " + dayOfWeek;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case MONTHLY:
 | 
				
			||||||
 | 
					                scheduleString = minute + " " + hour + " " + dayOfMonth + " * *";
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new CronExpressionException("Message period not implemented: '" + settings.getMessagePeriod() + "'");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: figure out actual invocation
 | 
				
			||||||
 | 
					        return scheduleString + " /home/nathanmcrae/personal_root/projects/numbers-station/run.sh --station \"" + settings.getName() + "\"";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static class CronExpressionException extends Exception {
 | 
				
			||||||
 | 
					        public CronExpressionException(String message) {
 | 
				
			||||||
 | 
					            super(message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package name.nathanmcrae.numbersstation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class MainRun {
 | 
				
			||||||
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
 | 
					        Main.main(args);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -454,7 +454,7 @@ public class StationSettingsController {
 | 
				
			|||||||
        if (osName.contains("win")) {
 | 
					        if (osName.contains("win")) {
 | 
				
			||||||
            WindowsScheduler.registerSchedule(settings);
 | 
					            WindowsScheduler.registerSchedule(settings);
 | 
				
			||||||
        } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) {
 | 
					        } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) {
 | 
				
			||||||
            logger.log(Level.SEVERE, "Unsupported OS " + osName);
 | 
					            LinuxScheduler.registerSchedule(settings);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            logger.log(Level.SEVERE, "Unsupported OS " + osName);
 | 
					            logger.log(Level.SEVERE, "Unsupported OS " + osName);
 | 
				
			||||||
            // TODO: Alert
 | 
					            // TODO: Alert
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -426,6 +426,7 @@ public class WindowsScheduler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return (stdout contents, stderr contents)
 | 
					     * @return (stdout contents, stderr contents)
 | 
				
			||||||
 | 
					     * TODO: don't assume that process has exited yet. If it does we don't want to hang.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static Pair<String, String> captureProcessOutput(Process process) throws IOException {
 | 
					    public static Pair<String, String> captureProcessOutput(Process process) throws IOException {
 | 
				
			||||||
        StringBuilder output = new StringBuilder();
 | 
					        StringBuilder output = new StringBuilder();
 | 
				
			||||||
@@ -435,10 +436,10 @@ public class WindowsScheduler {
 | 
				
			|||||||
             BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
 | 
					             BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
 | 
				
			||||||
            String line;
 | 
					            String line;
 | 
				
			||||||
            while ((line = reader.readLine()) != null) {
 | 
					            while ((line = reader.readLine()) != null) {
 | 
				
			||||||
                output.append(line);
 | 
					                output.append(line + "\n");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            while ((line = errorReader.readLine()) != null) {
 | 
					            while ((line = errorReader.readLine()) != null) {
 | 
				
			||||||
                error.append(line);
 | 
					                error.append(line + "\n");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user