我如何通过 ssh 连接到谷歌协作虚拟机?有没有比创建从 jupyter notebook 到远程服务器的 ssh 隧道更直接的方法?
7 回答
import random, string, urllib.request, json, getpass
#Generate root password
password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(20))
#Download ngrok
! wget -q -c -nc https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
! unzip -qq -n ngrok-stable-linux-amd64.zip
#Setup sshd
! apt-get install -qq -o=Dpkg::Use-Pty=0 openssh-server pwgen > /dev/null
#Set root password
! echo root:$password | chpasswd
! mkdir -p /var/run/sshd
! echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
! echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
! echo "LD_LIBRARY_PATH=/usr/lib64-nvidia" >> /root/.bashrc
! echo "export LD_LIBRARY_PATH" >> /root/.bashrc
#Run sshd
get_ipython().system_raw('/usr/sbin/sshd -D &')
#Ask token
print("Copy authtoken from https://dashboard.ngrok.com/auth")
authtoken = getpass.getpass()
#Create tunnel
get_ipython().system_raw('./ngrok authtoken $authtoken && ./ngrok tcp 22 &')
#Get public address and print connect command
with urllib.request.urlopen('http://localhost:4040/api/tunnels') as response:
data = json.loads(response.read().decode())
(host, port) = data['tunnels'][0]['public_url'][6:].split(':')
print(f'SSH command: ssh -p{port} root@{host}')
#Print root password
print(f'Root password: {password}')
ngrok用于创建通往机器的隧道并为其提供可公开访问的主机名。您需要注册,复制您的身份验证令牌,并在出现提示时将其提供给 Colab 笔记本。
完成后,它将打印出您的连接详细信息,例如:
SSH command: ssh -p12312 root@0.tcp.ngrok.io
Root password: abcdeLMh6vpNViGHQbXi
如果最后一步失败,请尝试再次运行单元或仅使用以下内容创建新单元并读取 JSON 输出以查找主机名和端口。
! curl -s http://localhost:4040/api/tunnels
这是另一种解决方案 - 本质上与@tamlyn 提出的相同,但要短得多。有一个colab-ssh连接器,可以自动执行该过程。您所要做的就是在ngrok上注册一个免费帐户。然后,您需要复制您的auth token。现在,在目标 Colab 笔记本中:
# Install colab_ssh
!pip install colab_ssh --upgrade
from colab_ssh import launch_ssh
launch_ssh('YOUR_NGROK_AUTH_TOKEN', 'SOME_PASSWORD')
您应该获取连接参数(注意端口)。现在您可以使用提供的详细信息连接到 Colab VM,例如:ssh -p 15892 root@0.tcp.ngrok.io
,15892
您需要更改的随机端口号在哪里。自然,系统会提示您输入先前设置的密码。
这显然受到免费 ngrok 帐户限制的限制,但对于小任务来说应该足够了。
如果你得到了IndexError: list index out of range
,别担心。根据我的经验,它仍然可以工作 - 您可以从ngrok active tunnels list获取端口和地址。
由于 Google 已决定阻止ngrok
Google Colab,因此您可能需要为 SSH 使用不同类型的隧道。你可以试试这个:
!pip3 install linus_colab_ssh
from colab_ssh import setup_ssh, loop_forever
public_key = '<YOUR_PUBLIC_SSH_KEY>'
setup_ssh(public_key)
loop_forever()
更多细节可以在这里找到。祝你好运!
这个 jupyter notebook说明了如何使用 ssh 反向隧道来执行此操作。
与前面的答案相比,ssh反向隧道的方法有以下区别:
- 在 colab 虚拟机上不需要 ngrok
- 仅当本地计算机还没有公共 IP 时才需要 ngrok
- 需要本地机器上的 sshd
来自https://github.com/tmate-io/tmate/issues/218:
!pkill -9 tmate
!wget -nc https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-i386.tar.xz &> /dev/null
!tar --skip-old-files -xvf tmate-2.4.0-static-linux-i386.tar.xz &> /dev/null
!rm -f nohup.out; bash -ic 'nohup ./tmate-2.4.0-static-linux-i386/tmate -S /tmp/tmate.sock new-session -d & disown -a' >/dev/null 2>&1
!./tmate-2.4.0-static-linux-i386/tmate -S /tmp/tmate.sock wait tmate-ready
!./tmate-2.4.0-static-linux-i386/tmate -S /tmp/tmate.sock display -p "Connect with SSH address: #{tmate_ssh}"
!./tmate-2.4.0-static-linux-i386/tmate -S /tmp/tmate.sock display -p "Connect with web: #{tmate_web}"
自 2021 年 9 月 11 日起生效。
从这个要点
import random, string, urllib.request, json, getpass
#Generate root password
password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(20))
#Download ngrok
! wget -q -c -nc https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
! unzip -qq -n ngrok-stable-linux-amd64.zip
#Ask token
print("Copy authtoken from https://dashboard.ngrok.com/auth")
authtoken = getpass.getpass()
#Create tunnel
get_ipython().system_raw('./ngrok authtoken $authtoken && ./ngrok tcp 22 &')
所以现在你的 ngrok 隧道已经建立(希望如此)。现在尝试安装 ssh 服务器。这意味着失败,但仍然这样做。
#Setup sshd
! sudo apt-get install openssh-server
由于上述命令失败,请运行此命令。
# if install fail run this, uncomment and run the below line
! sudo apt-get install openssh-server --fix-missing
现在运行它,这会对 ssh 配置进行基本更改,以确保您能够在 colab 中远程登录。
#Set root password
! echo root:$password | chpasswd
! mkdir -p /var/run/sshd
! echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
! echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
! echo "LD_LIBRARY_PATH=/usr/lib64-nvidia" >> /root/.bashrc
! echo "export LD_LIBRARY_PATH" >> /root/.bashrc
现在我们将尝试运行 ssh-daemon
get_ipython().system_raw('/usr/sbin/sshd -D &')
# to check if ssh is running on port 22 or not or installed or not
! sudo apt install net-tools
! netstat -plant | grep ssh
! which sshd
最后两个命令应该给出输出
/usr/bin/sshd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1008/sshd
获取 ssh 配置和凭据
# get_ipython().system_raw('./ngrok authtoken $authtoken && ./ngrok tcp 22 &')
with urllib.request.urlopen('http://localhost:4040/api/tunnels') as response:
data = json.loads(response.read().decode())
(host, port) = data['tunnels'][0]['public_url'][6:].split(':')
print(f'SSH command: ssh -p{port} root@{host}')
#Print root password
print(f'SSH password: {password}')
如果由于某种原因上述命令失败,请再次运行,直到它工作
您可以使用 在笔记本中执行 shell 命令!
,例如:
!echo "Echo in shell"
目前不支持通过 SSH 直接连接到后端。