Dale Roberts's solution works fine, but only when the remote machine can be seen directly from the Internet. After connection you can type
Links[]
and see
{LinkObject["[email protected],[email protected]", 3, 1],
LinkObject["[email protected],[email protected]", 56, 2],
LinkObject["[email protected],[email protected]", 57, 3]}
It means that the main link (the first) was opened through the ssh tunnel, but the preemptive link and the service link (the second and the third) was opened directly to the remote machine (it has 109.1.2.3 ip in this example).
If the remote machine is behind a router with port redirection this approach is unfortunately not worked. It is because MathLink
naively try to open the preemptive link and the service link to the remote machine ip which is now something like 192.168.1.123. This behaviour can not be changed from extarnal options like LinkName
and LinkHost
.
I found great solution here: Remote Kernel Strategies. It simply redefines MathLink`CreateFrontEndLink
. It was written for Mathematica 6, but it also works with Mathematica 9.
Now I can connect and see that all connections are through the ssh tunnel
Links[]
{LinkObject["[email protected],[email protected]", 3, 1],
LinkObject["[email protected],[email protected]", 57, 2],
LinkObject["[email protected],[email protected]", 58, 3]}
For further study, see excellent explanation in init.m in Remote Kernel Strategies.
I want to add some information about connecting to and disconnecting from the remote kernel without it's interrupting. It may be useful if you want to send a long task, turn off local machine and reconnect to the remote machine several days later.
I don't know the best place to post this information. This question is about connecting to the master kernel on the server while the subkernels are running. So I will be happy if you correct me.
I modify the last command in tunnel.sh
in Remote Kernel Strategies in the following way:
/usr/bin/ssh \
$SSH_OPTS \
-R 127.0.0.1:$MAIN_LINK_DATA_PORT:127.0.0.1:$MAIN_LINK_DATA_PORT \
-R 127.0.0.1:$MAIN_LINK_MESSAGE_PORT:127.0.0.1:$MAIN_LINK_MESSAGE_PORT \
-L $PREEMPTIVE_LINK_DATA_PORT:127.0.0.1:$PREEMPTIVE_LINK_DATA_PORT \
-L $PREEMPTIVE_LINK_MESSAGE_PORT:127.0.0.1:$PREEMPTIVE_LINK_MESSAGE_PORT \
-L $SERVICE_LINK_DATA_PORT:127.0.0.1:$SERVICE_LINK_DATA_PORT \
-L $SERVICE_LINK_MESSAGE_PORT:127.0.0.1:$SERVICE_LINK_MESSAGE_PORT \
$REMOTE_KERNEL_HOST \
"screen -wipe; \
screen -ls | grep MathKernel -q || \
screen -md -S MathKernel $REMOTE_KERNEL_PATH && \
screen -md -S Respawner screen -x MathKernel; \
sleep 1; \
screen -S MathKernel -X stuff `echo -e \"\\\\\\\$ParentLink=LinkCreate[\\\\\\\"$LINK_NAME\\\\\\\",LinkMode-\\\\\\\>Connect,LinkProtocol-\\\\\\\>\\\\\\\"TCPIP\\\\\\\"]\\\\\\\;\\\r\"`; \
sleep 20" >> $LOGFILE 2>&1
It starts screen session with MathKernel
name if it isn't exist. Then it connects to the existing session by
$ParentLink=LinkCreate["$LINK_NAME",LinkMode->Connect,LinkProtocol->"TCPIP"];
Without sleep
Mathematica doesn't have time to establish the connection.
For disconnecting I use
SetAttributes[Disconnect, HoldAll];
Disconnect[expr___] :=
Module[{links = {$ParentLink, MathLink`$ServiceLink,
MathLink`$PreemptiveLink}}, $ParentLink = Null;
LinkClose /@ links; MathLink`$PortNumber =.; SetOptions["stdout", FormatType->OutputForm];
expr]
Then you can simply run something like this
x = Sum[EulerPhi[n], {n, 10000000}]; // Disconnect
and x=...
will be evaluated after disconnection. MathLink`$PortNumber =.
is necessary to connect to the same ports after disconnecting. For convenienceDisconnect
can be added to init.m
.
Update 1: you have to run two screen
sessions and attach one to another because you can send commands only to attached sessions. You can directly connect to the screen
session by screen -x MathKenel
. It is useful if you want to check the state of your program from the mobile phone.
Update 2: LinkClose/@Links[]
is bad because it closes links to parallel subkernels. So I explicitly specify $ParentLink
, MathLink`$ServiceLink
, and MathLink`$PreemptiveLink
.
Update 3: Explicit port specification isn't needed.
Update 4: The terminal formatting is restored by SetOptions["stdout", FormatType->OutputForm]
. Thanks this answer.
Update 5: After reconnection custom syntax highlighting is dropped. You can repair it by
Scan[ToExpression[#, InputForm,
Function[name,
SyntaxInformation@Unevaluated[name] =
SyntaxInformation@Unevaluated[name], HoldAll]] &,
Names["Global`*"]];
Update 6: Mathematica 10 has libraries which can be incompatible with our SSH. If you have an error
ssh: symbol lookup error: ssh: undefined symbol: EVP_aes_128_ctr
or something like this then reset an environmental variable $LD_LIBRARY_PATH
by adding
export LD_LIBRARY_PATH=
to tunnel.sh
.