Last active
February 11, 2019 02:07
-
-
Save jtrive84/cd43eda7e3399fb1642c29b0b76f7bd9 to your computer and use it in GitHub Desktop.
Connect to remotely running Python kernel from localhost via Jupyter QtConsole.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# <>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<> | |
# Connect to a remote Python kernel via locally-running Jupyter QtConsole. | | |
# Created by James D. Triveri. | | |
# | | |
# Requirements: | | |
# | | |
# * Jupyter/IPython must be installed on both local and remote hosts. | | |
# | | |
# <>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<> | |
# Configuration and Setup | | |
# <>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<> | |
USERNAME="username" | |
LOCAL_JUPYTER="C:/Anaconda3/Scripts/jupyter.exe" | |
LOCAL_JUPYTER_QTCONSOLE="C:/Anaconda3/Scripts/jupyter-qtconsole.exe" | |
LOCAL_SSH_CONFIG="C:/cygwin64/home/username/.ssh/config" | |
REMOTEHOST="remotehost.com" | |
SSH_PORT="3337" | |
REMOTE_JUPYTER="/usr/bin/local/anaconda3/bin/jupyter" | |
REMOTE_IPYTHON="/usr/bin/local/anaconda3/bin/ipython" | |
# <>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<> | |
# Do not modify variables below this point!!! | | |
# <>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<>*<> | |
##### Bind reference to local and remote jupyter runtime directories ##### | |
LOCAL_KERNEL_DIR="$(${LOCAL_JUPYTER} --runtime-dir | sed -e 's/\\/\//g' | tr -d '\r\n')" | |
LOCAL_KERNEL_DIR="${LOCAL_KERNEL_DIR%%/}" | |
REMOTE_KERNEL_DIR_CMD="${REMOTE_JUPYTER} --runtime-dir" | |
REMOTE_KERNEL_DIR="$(ssh -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} ${REMOTE_KERNEL_DIR_CMD})" | |
REMOTE_KERNEL_DIR="${REMOTE_KERNEL_DIR%%/}" | |
##### Initialize kernel daemon on remote host ##### | |
ssh -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} "nohup ${REMOTE_IPYTHON} kernel > /dev/null &" | |
KERNEL_PID=$(ssh -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} "pgrep -n -u ${USERNAME} ipython") | |
##### Get most recently created file in remote jupyter directory ##### | |
REMOTE_KERNEL_FULL_PATH="${REMOTE_KERNEL_DIR}/kernel-${KERNEL_PID}.json" | |
KERNEL_FILENAME="$(basename ${REMOTE_KERNEL_FULL_PATH})" | |
REMOTE_KERNEL_FULL_PATH="${REMOTE_KERNEL_DIR}/${KERNEL_FILENAME}" | |
LOCAL_KERNEL_FULL_PATH="${LOCAL_KERNEL_DIR}/kernel-${KERNEL_PID}.json" | |
##### Delay progress until KERNEL_FILENAME becomes visible on remotehost ##### | |
KERNEL_FILE_IND=0 | |
while [[ ${KERNEL_FILE_IND} -eq 0 ]]; do | |
FILE_CMP_CMD="pushd ${REMOTE_KERNEL_DIR} > /dev/null; ls -1tr | tail -1" | |
LATEST_KERNEL_FILENAME=$(ssh -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} "${FILE_CMP_CMD}") | |
if [[ "${LATEST_KERNEL_FILENAME}" == "${KERNEL_FILENAME}" ]]; then | |
KERNEL_FILE_IND=1 | |
else | |
sleep 1s | |
fi | |
done | |
##### Copy kernel file from remotehost to localhost ##### | |
TS=$(date) | |
echo " + [${TS}] Copying ${KERNEL_FILENAME} to localhost." | |
pushd "${LOCAL_KERNEL_DIR}" > /dev/null | |
scp -P ${SSH_PORT} ${USERNAME}@${REMOTEHOST}:"${REMOTE_KERNEL_FULL_PATH}" . | |
TS=$(date) | |
if [ -e "${LOCAL_KERNEL_FULL_PATH}" ]; then | |
echo " + [${TS}] ${KERNEL_FILENAME} copied to localhost." | |
else | |
echo " + [${TS}] ${KERNEL_FILENAME} not copied to Windows - Exiting." | |
exit 1 | |
fi | |
##### Bind each port to support kernel connectivity ##### | |
STDIN_PORT_REGEX='[[:space:]]+"stdin_port":[[:space:]]+\K[0-9]{2,5}' | |
IOPUB_PORT_REGEX='[[:space:]]+"iopub_port":[[:space:]]+\K[0-9]{2,5}' | |
SHELL_PORT_REGEX='[[:space:]]+"shell_port":[[:space:]]+\K[0-9]{2,5}' | |
CONTROL_PORT_REGEX='[[:space:]]+"control_port":[[:space:]]+\K[0-9]{2,5}' | |
HB_PORT_REGEX='[[:space:]]+"hb_port":[[:space:]]+\K[0-9]{2,5}' | |
STDIN_PORT_NBR=$(grep -Po ${STDIN_PORT_REGEX} ${KERNEL_FILENAME}) | |
IOPUB_PORT_NBR=$(grep -Po ${IOPUB_PORT_REGEX} ${KERNEL_FILENAME}) | |
SHELL_PORT_NBR=$(grep -Po ${SHELL_PORT_REGEX} ${KERNEL_FILENAME}) | |
CONTROL_PORT_NBR=$(grep -Po ${CONTROL_PORT_REGEX} ${KERNEL_FILENAME}) | |
HB_PORT_NBR=$(grep -Po ${HB_PORT_REGEX} ${KERNEL_FILENAME}) | |
##### Initialize port forwarding ##### | |
TS=$(date) | |
echo " + [${TS}] Binding/Forwarding stdin_port." | |
ssh -F "${LOCAL_SSH_CONFIG}" -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} -f -N -L ${STDIN_PORT_NBR}:127.0.0.1:${STDIN_PORT_NBR} | |
wait | |
TS=$(date) | |
echo " + [${TS}] Binding/Forwarding iopub_port." | |
ssh -F "${LOCAL_SSH_CONFIG}" -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} -f -N -L ${IOPUB_PORT_NBR}:127.0.0.1:${IOPUB_PORT_NBR} | |
wait | |
TS=$(date) | |
echo " + [${TS}] Binding/Forwarding shell_port." | |
ssh -F "${LOCAL_SSH_CONFIG}" -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} -f -N -L ${SHELL_PORT_NBR}:127.0.0.1:${SHELL_PORT_NBR} | |
wait | |
TS=$(date) | |
echo " + [${TS}] Binding/Forwarding control_port." | |
ssh -F "${LOCAL_SSH_CONFIG}" -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} -f -N -L ${CONTROL_PORT_NBR}:127.0.0.1:${CONTROL_PORT_NBR} | |
wait | |
TS=$(date) | |
echo " + [${TS}] Binding/Forwarding hb_port." | |
ssh -F "${LOCAL_SSH_CONFIG}" -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} -f -N -L ${HB_PORT_NBR}:127.0.0.1:${HB_PORT_NBR} | |
wait | |
##### Launch Jupyter QtConsole ##### | |
TS=$(date) | |
echo " + [${TS}] Initializing Jupyter QtConsole." | |
"${LOCAL_JUPYTER_QTCONSOLE}" --existing "${LOCAL_KERNEL_FULL_PATH}" | |
wait | |
##### Shutdown remote once QtConsole session terminates ##### | |
KILL_SPEC="kill -9 ${KERNEL_PID}" | |
ssh -p ${SSH_PORT} ${USERNAME}@${REMOTEHOST} "${KILL_SPEC}" | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment