Interfacing
Connecting to a running Neurodesktop session via a plain shell
Section titled “Connecting to a running Neurodesktop session via a plain shell”You can start a Neurodesktop container using Docker or the Neurodesk App. If you want to connect to this running session using a shell you can do this as well:
docker ps# note the name of the running container, e.g. neurodeskapp-49977
# now connect to this containerdocker exec --user=jovyan -ti neurodeskapp-49977 bashAPI interface to Jupyter
Section titled “API interface to Jupyter”This currently does not work on Apple Silicon machines.
Install necessary tools, e.g. for macOS:
brew install coreutilsbrew install websocatOr for Linux:
wget https://github.com/vi/websocat/releases/download/v1.12.0/websocat.x86_64-unknown-linux-muslchmod +x websocat.x86_64-unknown-linux-muslsudo mv websocat.x86_64-unknown-linux-musl /usr/local/bin/websocatapt install jqStart a Jupyter notebook session, e.g. on EXAMPLE_API_URL=play-europe.neurodesk.org.
Then open a terminal in Jupyter and find your JupyterHub token and your username:
echo JUPYTERHUB_USER=$JUPYTERHUB_USERecho JPY_API_TOKEN=$JPY_API_TOKENNow you can interface with Jupyter through:
USER=$JUPYTERHUB_USERUSER_TOKEN=$JPY_API_TOKENAPI_URL=$EXAMPLE_API_URL
TERMINAL_RESPONSE=$(curl -k -s -X POST \ -H "Authorization: token $USER_TOKEN" \ "https://$API_URL/user/$USER/api/terminals" || echo '{"error": "curl_failed"}')
echo "Terminal API response: $TERMINAL_RESPONSE"
TERMINAL_NAME=$(echo "$TERMINAL_RESPONSE" | jq -r '.name // empty')
if [ -n "$TERMINAL_NAME" ] && [ "$TERMINAL_NAME" != "null" ] && [ "$TERMINAL_NAME" != "empty" ]; then echo "Terminal created successfully: $TERMINAL_NAME"else echo "Terminal creation failed" echo "Full response: $TERMINAL_RESPONSE"
# more info about the user echo "Checking user info..." USER_INFO=$(curl -k -s -H "Authorization: token $USER_TOKEN" "https://$API_URL/hub/api/users/$USER" || echo '{"error": "failed"}') echo "User info: $USER_INFO"fi
# Function to test WebSocket connectiontest_websocket_connection() { local token="$1"
echo "Testing WebSocket connection..."
# Test connection WS_TEST=$(echo '["stdin", "echo test_connection\r\n"]' | \ timeout 15 websocat --text "wss://$API_URL/user/$USER/terminals/websocket/$TERMINAL_NAME" \ -H "Authorization: token $token" 2>&1 | head -10)
if [ $? -eq 0 ] && [ -n "$WS_TEST" ]; then echo "WebSocket response: $WS_TEST"
# Check if we got expected output format if echo "$WS_TEST" | grep -q '\["stdout"'; then echo "WebSocket connection successful with proper output format" return 0 elif echo "$WS_TEST" | grep -q 'test_connection'; then echo "WebSocket connection successful" return 0 else echo "WebSocket connected but unexpected format" echo "Raw output: $WS_TEST" return 1 fi else echo "WebSocket connection failed" echo "Error: $WS_TEST" return 1 fi}
# Test with user tokenif test_websocket_connection "$USER_TOKEN"; then echo "WebSocket connection working with user token"else echo "WebSocket connection failed" echo "" echo "Additional debugging info:" echo "- Terminal exists: $TERMINAL_NAME" echo "- User token: ${USER_TOKEN}..." echo "- API accessible: $(curl -k -s -o /dev/null -w "%{http_code}" "$API_URL")" echo "- WebSocket URL: ws://$API_URL/user/$USER/terminals/websocket/$TERMINAL_NAME"fi
# Function to send command and get responsesend_command() { local cmd="$1"
echo "Testing command: $cmd"
local clean_api_url=${API_URL#*//}
local output="" for attempt in {1..3}; do echo " Attempt $attempt..."
echo "$ $cmd"
# Send command echo "[\"stdin\", \"$cmd\\r\\n\"]" | \ timeout 15 websocat --text \ "wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \ -H "Authorization: token $USER_TOKEN"
sleep 10
# get the terminal output local output=$(echo '["stdin", ""]' | \ timeout 15 websocat --text \ "wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \ -H "Authorization: token $USER_TOKEN")
if [ -n "$output" ]; then echo "$output" | \ grep '^\["stdout"' | \ sed 's/^\["stdout", *"//; s/"\]$//' | \ sed 's/\\u001b\[[?]*[0-9;]*[a-zA-Z]//g; s/\\r\\n/\n/g; s/\\r/\n/g' | \ # sed -n "/\$ $cmd/,/\$ /p" | \ sed '1d; $d' | \ grep -v "^$"
return 0 fi
echo "(no output), response: ${output}"
sleep 2 done
echo " Command failed after 3 attempts" echo " Output: $output" return 1}send_command "touch test3.txt"send_command "ls"send_command "ml fsl; fslmaths"send_command "pwd"send_command "ml ants; antsRegistration"
# To start an interactive terminal sessioninteractive_terminal() {
local clean_api_url=${API_URL#*//}
echo "=== Interactive Terminal Started ===" echo "Type 'exit' to quit" echo "=================================="
while true; do echo -n "$ " read -r user_cmd
# Exit condition if [[ "$user_cmd" == "exit" ]]; then echo "Terminal session ended." break fi
# Skip empty commands if [[ -z "$user_cmd" ]]; then continue fi
echo "Executing: $user_cmd"
# Send command
echo "[\"stdin\", \"$user_cmd\\r\\n\"]" | \ timeout 15 websocat --text \ "wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \ -H "Authorization: token $USER_TOKEN"
sleep 10
# get the terminal output local output=$(echo '["stdin", ""]' | \ timeout 15 websocat --text \ "wss://$clean_api_url/user/$USER/terminals/websocket/$TERMINAL_NAME" \ -H "Authorization: token $USER_TOKEN")
if [ -n "$output" ]; then echo "$output" | \ grep '^\["stdout"' | \ sed 's/^\["stdout", *"//; s/"\]$//' | \ sed 's/\\u001b\[[?]*[0-9;]*[a-zA-Z]//g; s/\\r\\n/\n/g; s/\\r/\n/g' | \ # sed -n "/\$ $user_cmd/,/\$ /p" | \ sed '1d; $d' | \ grep -v "^$"
else echo "(output error, response:) ${output}" fi
echo "" done}
interactive_terminal