I have a package that initiates some periodic tasks via the ScheduledTasks functionality. The tasks in question also require the use of parallel tools and the launching of external commands. Everything works if I load the package interactively either from Mathematica or MathKernel. However, I need a way to script this procedure, so that Mathematica is started and the package is loaded automatically.

So far, I have tried loading the core package file into the kernel (i.e. MathKernel <MyPackageSource.m), but the kernel exits as soon as the script file is loaded, whereas I need it to stay open to continue to service the ScheduledTasks. I also tried putting the package into the Autoload directory and starting up MathKernel to load it, but encountered a problem because my package uses Import to import a text file, and apparently the import infrastructure is not yet ready for use at the time my package is autoloaded.

So, my question is two-fold: 1. Is there a way to use Import[..., "Text"] inside an autoloaded package?, and 2. Is there an altogether better way to load a package into a Mathematica session in the context of a batch process?

• See this and linked topics: mathematica.stackexchange.com/q/131856/5478 – Kuba May 2 '17 at 19:05
• I will try the suggestions there in the context of my autoload solution, but what I'm really looking for is a way to do this without using Autoload. Is there a way to start mathematica and load an arbitrary package, from the command line? – tavr May 2 '17 at 19:11
• I see, ok, let's wait for someone with more experience in this area. – Kuba May 2 '17 at 21:07

I have tried loading the core package file into the kernel, but the kernel exits as soon as the script file is loaded, whereas I need it to stay open to continue to service the ScheduledTasks.

I think the kernel exiting is the problem here. You just need the main "thread" to stay in an idle loop so the background can run.

Here's a script file that starts a scheduled task and then stays looping while the task runs:

Print["Watching for file changes in ", Directory[]]
files = FileNames[];
checkForChangedFiles[] :=
(
latestfiles = FileNames[];
newfiles = Complement[latestfiles, files];
If[newfiles =!= {}, Print["Found new files: ", newfiles]];
removed = Complement[files, latestfiles];
If[removed =!= {}, Print["Files removed: ", removed];];
files = latestfiles;
)

While[True,
Pause[1]
]


Call this file watcher.m, and invoke it from command line:

\$ math -script watcher.m


You can test it by adding or removing files from a separate process.

In your case, you need to load a package. You can add that code in the beginning, where I have a function definition and before the RunScheduledTask call.

• I can confirm that the infinite loop keeps the kernel open when you load the package file as a script, and allows the scheduled tasks to be serviced. I was hoping for a more robust approach, but this does work. – tavr May 19 '17 at 20:36
• What's not robust about it? – Joel Klein May 19 '17 at 23:01
• Pause is keeping the master kernel open, but at the cost of blocking all further evaluations. This isn't much of a concern in batch mode, but it means that I cannot simply load my package in a batch procedure, but must nest it inside a script that keeps the master kernel spinning. Again, not a big deal, but not ideal either. I think what's needed is an option to keep math executable open indefinitely, or else math should respect pending ScheduledTask's and not exit at end of script. – tavr May 20 '17 at 0:37
• "at the cost of blocking all further evaluations" -- what do you mean? – Joel Klein Jun 6 '17 at 21:39

I made an automatic water misting fan. The temperature monitor software checks temperature at certain interval and decides if it should turn on/off the water misting fan. I think what the temperature monitor software does might meet your needs.

/Applications/Mathematica.app/Contents/SystemFiles/Links/JLink/JLink.jar


If you use Linux or Windows, you have to modify the path of MathKernel to create KernelLink.

/Applications/Mathematica.app/Contents/MacOS/MathKernel


Java (JDK 8):

import com.wolfram.jlink.KernelLink;

import java.util.Optional;

public static void main(String[] argv) throws MathLinkException {
}

"/Applications/Mathematica.app/Contents/MacOS/MathKernel"};
try {
System.out.println("Fatal error opening link: " + e.getMessage());
return Optional.empty();
}
}

String packagePath = System.getProperty("user.dir") + "/ac.m";
String loadPackage = "Get[\"" + packagePath + "\"]";
}

try {
e.printStackTrace();
}
}

int interval = 2000;
String expr  = "checkTemperature[]";
}

Runnable task = () -> {
try {
System.out.print(".");
e.printStackTrace();
}
};

while(true) {
try{
}
catch(Exception e){
}
}
}
}


Wolfram:

(* wemo switch https://github.com/iancmcc/ouimeaux *)
(* istats https://github.com/Chris911/iStats *)

cpuTemperature[] := Module[{command, xs, cs, position},
command = {"/usr/local/bin/istats", "extra"};
xs = RunProcess[command]["StandardOutput"] // ImportString[#, "CSV"] & // First;
cs = Map[Select[PrintableASCIIQ], Characters@xs] // Flatten;
position = FirstPosition[cs, "["] // First;
Take[cs, position-4] // StringJoin // StringCases[#, x__ ~~ ":" ~~ y__->y]&//First//ToExpression]

temperatureHighQ[highTemperature_] := Module[{temperature},
temperature = cpuTemperature[];
If[temperature > highTemperature, (Pause[1];
cpuTemperature[] > temperature), False]]

temperatureLowQ[lowTemperature_] := Module[{temperature},
temperature = cpuTemperature[];
If[temperature < lowTemperature, (Pause[1];
cpuTemperature[] < temperature), False]]

wemoSwitch[x_] := Module[{command},
If[x, Print["High"], Print["Low"]];
command =  {"/usr/local/bin/wemo", "switch", "aircondition",
If[x, "on", "off"]};
RunProcess[command]];

checkTemperature[] := Module[{high, low},
high = 50;
low  = 46;
Which[
temperatureHighQ[high], wemoSwitch[True] ,
temperatureLowQ[low], wemoSwitch[False]]]