Friday, November 27, 2015

How to run Matlab on a remote machine

You would think that launching Matlab jobs through the SSH connection to a remote Unix machine is as easy as running any other command in a terminal. Instead, you might find yourself stuck with log files filled up with GB's worth of error messages like Warning: Error reading character from command line and Error: Bad file descriptor, even though your script does not require any user input at all. What to do?

You could either look up answers for each of the encountered problems individually, or you can use the following guide that tries to address all of the potential pitfalls conveniently in one place.


How to use Matlab remotely

The easiest way to use Matlab remotely is to launch an SSH session with X11 forwarding enabled. You can then use Matlab as usual, including the GUI:

$ ssh -X username@remote.host.com
$ matlab &

However, chances are that the remote connection is too slow to update the GUI at a reasonable pace, making the interaction more painful than it should be. Instead, you may want to take a pass on X11 forwarding and work with Matlab simply on the command line:

$ ssh username@remote.host.com
$ matlab -nosplash -nodesktop

This will allow you to run scripts and type in any Matlab command as usual:.

Type exit to quit.

How to run a Matlab script in the background of a remote machine

This is where it gets tricky. You may well be aware that you can run a Matlab script from the command line with the -r flag:

$ matlab -nosplash -nodesktop -r myscript

However, what if your Matlab script is computationally intensive and runs for several days? You don't want to wait in front of the terminal until the process finishes. You could try to add a & to make the process launch in the background, but that will most likely end up in the following lovely error: Warning: Error reading character from command line. This is because Matlab is trying to read from stdin, which is not around when a process is executed in the background. An easy workaround is to wrap the Matlab command in a short shell script:

run_script.sh:

#!/bin/bash
matlab -nojvm -r 'myscript'

The script can then be invoked via:

$ chmod +x run_script.sh
$ ./run_script.sh &

However, there are at least three potential problems with this approach:

  • The process will not terminate even if the script has been executed successfully. This can be fixed by adding an exit statement to the matlab call.
  • All output will be directed to a file nohup.out, which can fill up quickly especially if your script generates a lot of status or error messages. A better way is to redirect the stdout and stderr streams either to the bit bucket (/dev/null) or to dedicated output files.
  • A soon as soon as the terminal is closed or the connection is interrupted, you will get a Write failed: Broken pipe. This where the nohup command (and its more sophisticated alternative screen) comes in handy. nohup is a handy command-line tool that will ignore a computer's hangup signal, which is usually invoked when a terminal is closed or the user logs out.

The complete solution thus looks like this:

run_script.sh:

#!/bin/bash
nohup matlab -nojvm -r 'myscript;exit'

This file can then be executed in the background with one of the three following commands, depending on whether you want to ignore all output, just stdout, or just stderr:

$ ./run_script.sh > /dev/null 2>&1 &
$ ./run_script.sh > /dev/null 2> err.txt &
$ ./run_script.sh > log.txt 2> /dev/null &

Note that if you are running this on a Mac, you might have to $unsetenv DISPLAY first (although I haven't tried this myself).