4
$\begingroup$

Suppose I launch many parallel Mathematica scripts with a command like

#!/bin/bash
math -run '<<MyScript.m someparameters'

My license has a limited number of kernels. So, if I launch too many, one of these jobs will produce an output such as

    Mathematica 12.2.0 Kernel license you are using has expired.
#...
    Enter your Activation key [format xxxx-xxxx-xxxxxx]: 

And then waits.

I would be happy with either of these solutions

  1. A tool that can check whether a mathematica kernel is available or not. So I can run it first, and wait until I get a green light.
  2. An option like --exit-if-no-licence-available that just exists with nonzero status without prompting the user for a license. So I can just restart the job periodically until it succeeds.
  3. A modification of the above script that allows me to feed newlines to the prompts so that I can restart the job.

To put this in context, I launch all these jobs in a cluster and they go in their own nodes, so I don't have interactive access, even if I want to.

$\endgroup$
8
  • $\begingroup$ Is it not possible to just launch the exact number of kernels that your license allows instead, thus sidestepping this problem? $\endgroup$
    – MarcoB
    Commented Jan 12, 2021 at 17:31
  • $\begingroup$ I will have to launch hundreds of jobs and it's just more convenient for me to launch them all at once and leave it running overnight. I could probably write a script that does it, but I was hoping for a more automated solution. $\endgroup$
    – MannyC
    Commented Jan 12, 2021 at 17:35
  • $\begingroup$ There's probably some way to grep the output for "Activation key" or similar and exit(1) if it's found, but the math tool appears to have a bit of weird readline behaviour that I don't know how to get around. $\endgroup$
    – Carl Lange
    Commented Jan 12, 2021 at 17:40
  • $\begingroup$ Sorry if I'm not following: if I try to grep the output, won't I be stuck at the prompt anyway, even before entering grep? $\endgroup$
    – MannyC
    Commented Jan 12, 2021 at 23:46
  • 1
    $\begingroup$ I have written something like this as a powershell script on windows. It uses an extra process and redirects input and output, reads output and checks it for the missing-license message and if it appears kills the process. It is kind of ugly but serves the purpose. On a unixish machine you should be able to do something along these lines using co-processes or expect. For how to do that you probably better want to ask different sites/communities... $\endgroup$ Commented Jan 13, 2021 at 16:30

2 Answers 2

1
$\begingroup$

I have written something like this as a powershell script on windows. It uses an extra process and redirects input and output, reads output and checks it for the missing-license message and if such a message appears kills the process. It is kind of ugly but serves the purpose and runs since about two years every night running a testsuite started by the windows task manager (windows equivalent of cron). Here is a code snippet of what I do in that script, $math_exec is the full path to the mathematica executable you want to call, the script name and arguments would come in as $args:

$proc_info = New-Object System.Diagnostics.ProcessStartInfo
$proc_info.FileName = $math_exec
$proc_info.RedirectStandardOutput = $true
$proc_info.UseShellExecute = $false
$proc_info.Arguments = "-script $($args -join ' ')"

$mma_process = New-Object System.Diagnostics.Process
$mma_process.StartInfo = $proc_info
$mma_process.Start() | Out-Null

# give mathematica some time to start, then check whether it complained about licenses...
Sleep 5
$num_lines_to_check = 5;
$output_str = ""
For ($i=1; $i -le $num_lines_to_check; $i++){
    $line_str = $mma_process.StandardOutput.ReadLine()
    Write-Host $line_str
    $output_str = $output_str + "`n" + "$line_str"
    
}
$license_lines = ($output_str | Select-String "Licensing\\mathpass" | Measure-Object -Line)
if ($license_lines.Lines -ne 0) {
    Write-Logfile "ERROR: there was a licensing issue when calling math.exe!"
    $mma_process.Kill()
}

(this code was inspired by this answer). On a unixish machine you should be able to do something along these lines using co-processes or expect. You can find instructions about using these tools elsewhere...

Note: I am anything but a decent powershell expert, so there might be much better ways to do this in powershell. If someone happens to read this with suggestions, please go ahead...

$\endgroup$
0
$\begingroup$

A possible solution in bash is the following: we use the fact that (at least on Linux) math gives exit status 85 when it doesn't find a valid license. So we can make a loop that retries until the exit status is not 85.

In principle one could also retry until zero, but this would create infinite loops if you have bugs in the code.

In any case, a working template is the following

#!/usr/bin/bash

exit=85

while [ $exit -eq 85 ]
do
    math -noprompt -run '<insert commands here>'
    exit=$?
    if [ $exit -eq 85 ]; then
        echo "Waiting 3 seconds and then retrying..."
        sleep 3
    fi
done

The crucial thing is the -noprompt that does not prompt the user for a license but simply quits.

For those unfamiliar with bash $? contains the exit status of the previous command. This also means that if math is not the last command inside the loop the script won't work.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.