blob: 4e11332d300b230847494636d73a33b550098477 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
# jupyter_safe_port
```
usage: jupyter_safe_port [-hcdf] {host} [port]
Discovers the next TCP port available for your notebook server and returns
execution instructions. If the argument '-c' is present and the requested
port is already bound on the remote host, return the SSH connection string
Positional arguments:
host host name or IP of remote system
port notebook server port to poll (default: 1024)
Arguments:
-h show this usage statement
-c only generate the SSH connection string
-d dump ports (useful in scripts)
format: local remote
-f apply SSH argument to daemonize session (i.e. ssh -f)
```
## Install
```
./install.sh --prefix=/usr/local
```
## Examples
_Oh no! I need to run two notebook servers on a remote system but which ports should I use?_
```
$ jupyter_safe_port example.lan
Execute on example.lan:
jupyter notebook --no-browser --port=1024
Connect via:
ssh -N -L1024:localhost:1024 user@example.lan
```
You start the first notebook server. Now run `jupyter_safe_port` again...
```
$ jupyter_safe_port example.lan
Execute on example.lan:
jupyter notebook --no-browser --port=1025
Connect via:
ssh -N -L1025:localhost:1025 user@example.lan
```
The local port 1024 is already bound to the first server so it gives you 1025. On the remote system, `example.lan`, port 1024 is bound too so it returns 1025 as well. What if you want to use a higher port number on `example.lan`? Let's see...
```
$ jupyter_safe_port example.lan 8080
Execute on example.lan:
jupyter notebook --no-browser --port=8081
Connect via:
ssh -N -L1026:localhost:8081 user@example.lan
```
Oops, you forgot about that web server test. 8080 is already bound so you're given 8081 instead. Locally 1024 and 1025 are already bound so `jupyter_safe_port` returns 1026.
Let's say you have closed your laptop and lost all of your connections. If you can remember the remote port you used then `-c` will get you up and running in no time...
```
$ jupyter_safe_port example.lan -c 8081
Connect via:
ssh -N -L1024:localhost:8081 user@example.lan
```
## Scripting
You can use `jupyter_safe_port` in your scripts. `-d` returns the local port followed by the remote port.
```
$ jupyter_safe_port example.lan -d 8081
1024 8081
```
Here are a few ways to use it...
```shell
#!/usr/bin/env bash
if type -p jupyter_safe_port &>/dev/null; then
echo "jupyter_safe_port is not installed" >&2
exit 1
fi
result=$(jupyter_safe_port -d $server)
if [ -z "$result" ]; then
# jupyter_safe_port failed
# case 1: not enough arguments
# case 2: invalid argument
# case 3: invalid port range
# case 4: ssh failed to connect to $server
exit 1
fi
# Extract ports from result
read $port_local $port_remote <<< "$result"
if (( port_remote < 0 )); then {
# case 1: no remote ports available
# case 2: if using '-c', no service is present on the requested port
exit 1
}
# Spawn a local screen session to manage a remote jupyter server.
# You'd really want to use screen on the remote instead... This is just an example.
screen -dmS "jupyter_$server_$remote_port" ssh $server "source ~/miniconda3/etc/profile.d/conda.sh \
&& conda activate XYZ \
&& jupyter notebook --no-browser --port=$port_remote"
# Forward the ports to the local system
echo "Forwarding $port_remote to localhost:$port_local"
echo "To interrupt the session press: ctrl-c
ssh -N $port_local:localhost:$port_remote $server
```
|