基本的ssh操作
ssh登录与ssh配置文件
使用ssh可以从一台设备登录到另一台已开启sshd服务的远程设备。
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ ssh yukari@172.28.24.152
The authenticity of host '172.28.24.152 (172.28.24.152)' can't be established.
ECDSA key fingerprint is SHA256:YSCMU48vJ8btRmdqgWLz8/VhMR3xjUIQn64K4MX/EgE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Password:
yukari@SALICYLIC:~$
ssh_config是存储OpenSSH配置信息的文本文件,用户个人的ssh_config配置储存在~/.ssh/config下。一条合法的配置格式如下
Host salic
HostName 172.28.24.152
User yukari
其中Host表示配置名,HostName表示远程设备地址,User表示登录的用户名。
在~/.ssh/config中添加上述配置后,可以通过设定的配置名进行更为简便的登录:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ vim ~/.ssh/config
Host salic
HostName 172.28.24.152
User yukari
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
coli@DESKTOP-J45M1NUM:~$ ssh salic
Password:
yukari@SALICYLIC:~$
ssh密钥登陆
除了使用密码进行登录身份验证之外,OpenSSH还支持通过密钥完成登录身份验证。
一对ssh密钥由私钥和公钥两个文件组成,它们是两段不同的复杂随机文本。一段数据由公钥加密后可以由其对应的私钥解密还原,而在没有私钥的情况下,仅根据公钥和密文的来推断加密前的数据被认为是不可实现的。因此,密钥可被用于身份验证:用户在服务器端和客户端分别存储公钥和私钥,需要身份验证时,服务器端将一段加密后的文本发送到客户端,客户端将通过私钥将密文解密后发回服务器端,如果服务器端收到的文本与加密前的文本一致,那么用户身份得以验证。
利用ssh-keygen可以生成一组全新的ssh密钥:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/coli/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/coli/.ssh/id_rsa
Your public key has been saved in /home/coli/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:NNxg9U2L1+XdtcxDVOxfobNrQ5Qf/IBwubrCaSJHUQY coli@DESKTOP-J45M1NUM
The key's randomart image is:
+---[RSA 3072]----+
| E.o.. .o+=|
| ooo..o++=B|
| o+ .oooB**|
| .. . o*.o+|
| .S .. +.=|
| . . o .o|
| . . . .. . |
| . o = . + |
| o o . . . |
+----[SHA256]-----+
coli@DESKTOP-J45M1NUM:~$ ls ~/.ssh
$ ls -al ~/.ssh
total 8
drwx------ 1 coli coli 4096 Mar 3 08:43 .
drwxr-xr-x 1 coli coli 4096 Mar 3 08:43 ..
-rw------- 1 coli coli 474 Mar 21 19:50 config
-rw------- 1 coli coli 2602 Mar 21 20:01 id_rsa
-rw------- 1 coli coli 565 Mar 21 20:01 id_rsa.pub
-rw-r--r-- 1 coli coli 222 Mar 21 19:48 known_hosts
coli@DESKTOP-J45M1NUM:~$
其中/home/coli/.ssh/id_rsa指定了生成的密钥文件的储存位置,passphrase是私钥口令,每次使用私钥登录前都需要输入此口令以启用私钥,相当于给私钥再设置一个密码。
按照其默认配置(全部留空)生成的私钥文件储存在/home/coli/.ssh/id_rsa,公钥文件储存在/home/coli/.ssh/id_rsa.pub。
要通过密钥登录到远程设备,还需要将公钥复制到远程设备的~/.ssh/authorized_keys下,可以通过scp将文件传输到远程设备:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ scp ~/.ssh/id_rsa.pub salic:~/.ssh/id_rsa.pub
Password:
id_rsa.pub 100% 565 264.4KB/s 00:00
coli@DESKTOP-J45M1NUM:~$ ssh salic
Password:
yukari@SALICYLIC:~$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
yukari@SALICYLIC:~$ logout
Connection to 172.28.24.152 closed.
coli@DESKTOP-J45M1NUM:~$ ssh salic
yukari@SALICYLIC:~$
配置成功后,你即可通过密钥验证的方式直接登录到远程设备,而不需要输入密码。
需要注意的是,只有在.ssh文件夹和密钥文件访问权限配置正确的情况下,密钥认证才能正确进行。具体说来,本地和远程的.ssh文件夹应当拥有700 rwx------(仅本人用户可读写访问)权限,而本地的私钥文件则应当拥有600 rw-------(仅本人用户可读写)权限。过于如果相应文件或文件夹的权限过于开放,那么ssh会禁用密钥验证。
默认情况下,OpenSSH会默认用~/.ssh下的id_rsa文件作为私钥尝试登录。如果你有多台远程设备,建议你分别使用不同的密钥对。要为不同的远程设备配置不同的密钥,你可以在~/.ssh/config中指定IdentityFile:
Host salic
HostName 172.28.24.152
User yukari
IdentityFile ~/.ssh/salic.id_rsa
此后登录salic时ssh客户端将使用~/.ssh/salic.id_rsa为私钥进行身份验证。
ssh代理跳板与端口转发
ssh代理跳板
一些情况下,不是所有设备都能够直接访问:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ ssh yukari@172.28.24.104
ssh: connect to host 172.28.24.104 port 22: Resource temporarily unavailable
coli@DESKTOP-J45M1NUM:~$ ssh salic
yukari@SALICYLIC:~$ ssh yukari@172.28.24.104
Password:
yukari@CITRIC:~$
在这个例子中,你无法通过本地设备直接登录到远程设备172.28.24.104,而需要通过另一台设备中转。这可能是由于该设备仅允许来自特定网段的连接,而你的本地设备不在允许规则内;或者远程设备是一个局域网设备,且与你的本地设备不在同一个局域网内。通常,用于登录中转的设备被称为代理跳板(proxy jump)。
在这种情况下,你可以通过ssh选项-J指定ssh代理跳板,或者在配置文件中指定ProxyJump项:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ ssh -J salic yukari@172.28.24.104
Password:
yukari@CITRIC:~$ logout
Connection to 172.28.24.104 closed.
coli@DESKTOP-J45M1NUM:~$ vim ~/.ssh/config
Host salic
HostName 172.28.24.152
User yukari
IdentityFile ~/.ssh/salic.id_rsa
Host citric
HostName 172.28.24.104
User yukari
ProxyJump salic
~
~
~
~
~
~
~
~
~
coli@DESKTOP-J45M1NUM:~$ ssh citric
Password:
yukari@CITRIC:~$
同样,你可以在citric和本地分别配置公钥和私钥,从而实现免密码登录。
端口转发
不同的设备处于不同的网络环境,但ssh可以通过端口转发以实现不同设备之间的网络数据交换。
ssh的端口转发分为远程转发和本地转发两种类型,分别用可于远程设备访问本地网络服务和本地访问远程设备网络服务。
下面将介绍端口转发的几种常用场景。
远程转发------反向ssh
scp命令可以在本地设备和远程设备之间传递文件。很多时候,我们希望在远程设备的工作目录与本地设备的特定目录之间进行文件交换(下载文件)。但是在不少情况下,远程设备无法通过ip地址连接到本地,因此我们只能依靠在本地打开一个新的命令行来传递文件。然而,在本地使用scp时需要指定远程文件的绝对路径 ,很方便。ssh的远程转发可以帮我们解决这个问题。
远程转发的ssh命令行参数格式为-R remoteport:localhost:localport,ssh_config的配置格式为RemoteForward remoteport host:hostport
设置远程转发后,远程设备中所有发送到remoteport端口的数据将通过ssh隧道转发到本地的localport端口。
此时你只需要在本地开启sshd服务,即可在通过转发的端口建立反向的ssh通道,从而在远程设备上使用scp传输文件
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ mkdir ~/downloads/
coli@DESKTOP-J45M1NUM:~$ sudo service ssh start
[sudo] password for coli:
coli@DESKTOP-J45M1NUM:~$ ssh -R 22222:localhost:22 salic
yukari@SALICYLIC:~$ cd data
yukari@SALICYLIC:~/data$ scp -P 22222 output.jpg coli@localhost:~/downloads/
output.jpg 100% 2465 463.2KB/s 00:00
yukari@SALICYLIC:~/data$ logout
Connection to 172.28.24.152 closed.
coli@DESKTOP-J45M1NUM:~$ ls ~/downloads/
output.jpg
coli@DESKTOP-J45M1NUM:~$
⚠注意
端口没有用户认证机制,建立远程转发后,远程设备上的所有用户都能够访问到你所转发的端口,从而能够通过ssh试图访问你的本地设备。
远程转发------网络服务转发
考虑这样一种情况:你想在远程设备上使用pip安装一个python包,或者安装一个R包,但是你的远程设备没有连接到互联网,你该如何操作?
最简单的做法是将先文件下载到本地,然后通过scp传输到远程设备,最后离线安装。但这对于哪些拥有复杂依赖的包来说十分不方便。
幸运的是,通过ssh远程端口转发,我们可以让远程设备访问到本地的网络服务:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ sudo apt install squid
[sudo] password for coli:
Preparing to unpack .../4-ssl-cert_1.0.39_all.deb ...
Unpacking ssl-cert (1.0.39) ...
Selecting previously unselected package squid.
Preparing to unpack .../5-squid_4.10-1ubuntu1.5_amd64.deb ...
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
Unpacking squid (4.10-1ubuntu1.5) ...
Setting up squid-langpack (20191103-1) ...
Setting up ssl-cert (1.0.39) ...
Setting up libdbi-perl:amd64 (1.643-1ubuntu0.1) ...
Setting up libecap3:amd64 (1.0.1-3.2ubuntu1) ...
Setting up squid-common (4.10-1ubuntu1.5) ...
Setting up squid (4.10-1ubuntu1.5) ...
Setcap worked! /usr/lib/squid/pinger is not suid!
invoke-rc.d: could not determine current runlevel
Created symlink /etc/systemd/system/multi-user.target.wants/squid.service → /lib/systemd/system/squid.service.
invoke-rc.d: could not determine current runlevel
Processing triggers for ufw (0.36-6) ...
Processing triggers for systemd (245.4-4ubuntu3.11) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...
coli@DESKTOP-J45M1NUM:~$ sudo vim /etc/squid/squid.conf
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
include /etc/squid/conf.d/*
# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
#http_access allow localnet
http_access allow localhost
# And finally deny all other access to this proxy
#http_access deny all
http_access allow all
# TAG: adapted_http_access
# Allowing or Denying access based on defined access lists
#
# Essentially identical to http_access, but runs after redirectors
coli@DESKTOP-J45M1NUM:~$ sudo service squid start
coli@DESKTOP-J45M1NUM:~$ ssh -R 3129:localhost:3128 salic
yukari@SALICYLIC:~$ export http_proxy=http://127.0.0.1:3128
yukari@SALICYLIC:~$ export https_proxy=http://127.0.0.1:3128
yukari@SALICYLIC:~$ curl www.baidu.com
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
yukari@SALICYLIC:~$
其中,squid是安装在本地的http代理客户端,它可以将所有发送到本地3128端口的http请求解析并转发给相应的目标。
ssh远程转发-R 3129:localhost:3128使得远程设备上所有发送到3129端口的数据转发到本地的3128端口,从而交给squid处理。
远程设备上所设置的环境变量http_proxy和https_proxy能够让所有http和https网络请求发送给远程设备的3129端口,进而被转发到本地3128端口交由squid处理。
你也可以使用3129之外的其他端口,只需保证ssh转发的端口和http_proxy转发到的端口一致即可。
http_proxy和https_proxy变量的设置是一次性的,仅适用于当前命令行。你可以将这两句话添加到~/.bashrc使得每次登录时自动设置这两个变量。
这里的ssh远程转发的命令行参数可以在ssh_config中设置为RemoteForward 3129 localhost:3128
如果你使用Windows下的OpenSSH客户端登录远程设备,那么你需要在Windows下安装squid或其他代理工具,并在ssh时指定对应的转发端口。
⚠注意
端口没有用户认证机制,建立远程转发后,远程设备上的所有用户都能够访问到你所转发的端口,从而能够通过你的本地代理访问网络。
本地转发------访问远程设备网络
ssh允许本地设备监听远程设备端口(准确地说,是将远程设备的某些特定端口转发到本地的特定端口)。通过这种方法,你可以在本地访问远程设备的网络服务。
例如,python的http.server (python3)或SimpleHTTPServer (python2)模块可以提供非常简单的http服务,包括文件索引和下载功能。
而且操作异常简单:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
随后打开浏览器,访问http://localhost:8080,就可以看到类似这样的界面:
Directory listing for /
Directory listing for /
这里显示的就是本地~文件夹下的文件和文件夹,单击页面上的文件链接会下载文件。
如果用ssh本地转发连接到远程设备,并在远程设备开启http服务:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
127.0.0.1 - - [24/May/2022 20:58:27] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [24/May/2022 21:01:03] "GET /downloads/ HTTP/1.1" 200 -
^C
Keyboard interrupt received, exiting.
coli@DESKTOP-J45M1NUM:~$ ssh -L 8081:172.28.24.152:8080 salic
yukari@SALICYLIC:~$ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
此时打开浏览器访问http://localhost:8081,就可以看到服务器上home文件夹的内容:
Directory listing for /
Directory listing for /
这里显示的是SALICYLIC远程服务器~文件夹下的文件和文件夹,单击页面上的文件链接即可从远程服务器上下载文件。
本地转发在ssh_config中的设置格式为LocalForward 8081 172.28.24.152:8080。
sshfs:将远程存储挂载为文件系统
sftp是一种远程文件传输协议,能够利用ssh协议在本地和远程之间拷贝文件。较新的scp命令行程序就利用sftp协议传输文件。
利用命令行程序传输文件通常较为不便,一次只能传输一个完整的文件夹,或者需要单独指定每个文件的路径。
在远程和本地间选择性传输大量文件时,图形化的用户界面能够带来很大的方便。
WinSCP和FileZilla是常用的图形化文件管理工具,支持sftp远程文件传输协议,通常可以满足常规的文件传输需求。
这里我们介绍一种基于WSL和sshfs的、更加原生和易用的解决方案。
WSL是一种在Windows系统中运行Linux程序的方法,其中新版(WSL2)可以运行完整的Linux内核。sshfs是一种文件系统,它借助Linux内核的功能,将远程存储挂载为本地文件系统。结合Windows对WSL文件系统的支持,我们可以Windows的资源管理器下直接访问远程设备存储。
在使用之前,你需要先安装WSL,并确保WSL版本为2。
如果你一定要使用WSL1
不建议在WSL1下使用sshfs
由于sshfs需要用到Linux内核模块FUSE,而WSL1不支持Linux内核,所以WSL1原生不支持sshfs。
尽管你可以通过某些手段进行模拟,但是总的来说效果不佳。
sshfs的安装需要root权限
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ sudo apt install sshfs
[sudo] password for coli:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
sshfs
0 upgraded, 1 newly installed, 0 to remove and 80 not upgraded.
Need to get 43.5 kB of archives.
After this operation, 123 kB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu focal/universe amd64 sshfs amd64 3.6.0+repack+really2.10-0ubuntu1 [43.5 kB]
Fetched 43.5 kB in 1s (40.8 kB/s)
Selecting previously unselected package sshfs.
(Reading database ... 52945 files and directories currently installed.)
Preparing to unpack .../sshfs_3.6.0+repack+really2.10-0ubuntu1_amd64.deb ...
Unpacking sshfs (3.6.0+repack+really2.10-0ubuntu1) ...
Setting up sshfs (3.6.0+repack+really2.10-0ubuntu1) ...
Processing triggers for man-db (2.9.1-1) ...
coli@DESKTOP-J45M1NUM:~$
文件系统的挂载则不需要root权限。例如,如果要将远程设备salic的用户文件夹挂载到本地,只需要在WSL中执行:
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ mkdir ~/mnt
coli@DESKTOP-J45M1NUM:~$ sshfs salic:/home/yukari ~/mnt
coli@DESKTOP-J45M1NUM:~$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sdc 263174212 4278568 245457488 2% /
none 4031704 32 4031672 1% /mnt/wslg
none 4031704 4 4031700 1% /mnt/wsl
tools 83886076 57364804 26521272 69% /init
none 4029656 0 4029656 0% /dev
none 4031704 4 4031700 1% /run
none 4031704 0 4031704 0% /run/lock
none 4031704 0 4031704 0% /run/shm
none 4031704 0 4031704 0% /run/user
tmpfs 4031704 0 4031704 0% /sys/fs/cgroup
drivers 83886076 57364804 26521272 69% /usr/lib/wsl/drivers
lib 83886076 57364804 26521272 69% /usr/lib/wsl/lib
none 4031704 76 4031628 1% /mnt/wslg/versions.txt
none 4031704 76 4031628 1% /mnt/wslg/doc
drvfs 83886076 57364804 26521272 69% /mnt/c
drvfs 403832828 146119192 257713636 37% /mnt/d
salic:/home/yukari 14290771910 9655851976 4634919934 68% /home/coli/mnt
coli@DESKTOP-J45M1NUM:~$ ls -al ~/mnt
total 52
drwxr-xr-x 1 1003 1003 4096 Dec 28 2021 ./
drwxr-xr-x 14 coli coli 4096 Mar 3 08:43 ../
-rw------- 1 1003 1003 8432 Mar 21 22:20 .bash_history
-rw-r--r-- 1 1003 1003 220 Dec 28 2021 .bash_logout
-rw-r--r-- 1 1003 1003 807 Dec 28 2021 .bash_profile
drwxr-xr-x 1 1003 1003 4096 Feb 18 15:20 .config/
drwx------ 1 1003 1003 4096 Mar 21 20:05 .ssh/
drwxrwxrwx 1 1003 1003 4096 Jan 9 15:30 software/
drwxrwxrwx 1 1003 1003 4096 Mar 15 11:34 data/
coli@DESKTOP-J45M1NUM:~$
可以看到远程设备上的存储已经被到挂载wsl文件系统的~/mnt[1]下,你可以像本地文件一样编辑、移动或删除其中的文件。
[1]sshfs仅支持将远程存储挂载到wsl文件系统下,不支持挂载到windows文件系统(即wsl中的/mnt/c等)下
但是,你现在还不能从Windows资源管理器中直接访问挂载的文件夹,因为Windows和WSL的用户权限不完全相同。要使Windows资源管理器能够直接访问挂载的文件夹,你还需要在挂载时添加参数-o allow_other
Ubuntu-22.04
coli@DESKTOP-J45M1NUM:~$ umount ~/mnt
coli@DESKTOP-J45M1NUM:~$ sshfs -o allow_ohter -o follow_symlinks salic:/home/yukari ~/mnt
fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf
coli@DESKTOP-J45M1NUM:~$ sudo vi /etc/fuse.conf
# /etc/fuse.conf - Configuration file for Filesystem in Userspace (FUSE)
# Set the maximum number of FUSE mounts allowed to non-root users.
# The default is 1000.
#mount_max = 1000
# Allow non-root users to specify the allow_other or allow_root mount options.
user_allow_other
~
~
~
~
~
~
~
~
~
~
coli@DESKTOP-J45M1NUM:~$ sshfs -o allow_other salic:/home/yukari ~/mnt
coli@DESKTOP-J45M1NUM:~$
umount ~/mnt用于卸载先前挂载在~/mnt的远程文件夹;
只有在/etc/fuse.conf配置文件中取消注释最后一行#user_allow_other后,普通用户才能够启用-o allow_other选项,该文件的编辑需要root权限。
重新挂载后,你可以通过地址\\wsl.localhost\Ubuntu-22.04\home\coli\mnt在资源管理器中直接访问到远程存储,并像本地文件一样对远程文件进行新建、编辑、移动或删除[1]。
[1]要使远程存储中的链接可用,还需要启用-o follow_symlinks选项,否则链接将显示为不可打开的文件而非文件夹。
于是,你就可以在Windows资源管理器内直接完成本地文件和远程文件的交换了。
不仅如此,你还可以直接使用Windows应用打开或编辑\\wsl.localhost\Ubuntu-22.04\home\coli\mnt下的远程文件,或者将文件下载或者保存到该路径,所有更改和创建都会直接应用到远程设备上。
远程数据访问
除了传输文件,ssh进行还可以用来直接传输数据。在本地运行ssh user@host command会在远程设备上执行command命令,并将结果输出到本地的标准输出。根据这一特性,我们可以在R、python等应用程序中通过ssh命令来读取远程设备上的数据。这样可以避免在本地保留大量临时数据,并省去数据版本校对和同步的麻烦。
Ubuntu-22.04
yukari@SALICYLIC:~/mydata$ cat data.csv
Tree,age,circumference
1,118,30
1,484,58
1,664,87
1,1004,115
1,1231,120
1,1372,142
1,1582,145
2,118,33
2,484,69
2,664,111
2,1004,156
2,1231,172
2,1372,203
2,1582,203
3,118,30
3,484,51
3,664,75
3,1004,108
3,1231,115
3,1372,139
3,1582,140
4,118,32
4,484,62
4,664,112
4,1004,167
4,1231,179
4,1372,209
4,1582,214
5,118,30
5,484,49
5,664,81
5,1004,125
5,1231,142
5,1372,174
5,1582,177
yukari@SALICYLIC:~/mydata$
coli@DESKTOP-J45M1NUM:~$ ssh citric head -n 5 ~/mydata/data.csv
Tree,age,circumference
1,118,30
1,484,58
1,664,87
1,1004,115
coli@DESKTOP-J45M1NUM:~$ R --quiet
> library(data.table)
data.table 1.14.3 using 1 threads (see ?getDTthreads). Latest news: r-datatable.com
> fread(cmd="ssh citric cat ~/mydata/data.csv")
Tree age circumference
1: 1 118 30
2: 1 484 58
3: 1 664 87
4: 1 1004 115
5: 1 1231 120
6: 1 1372 142
7: 1 1582 145
8: 2 118 33
9: 2 484 69
10: 2 664 111
11: 2 1004 156
12: 2 1231 172
13: 2 1372 203
14: 2 1582 203
15: 3 118 30
16: 3 484 51
17: 3 664 75
18: 3 1004 108
19: 3 1231 115
20: 3 1372 139
21: 3 1582 140
22: 4 118 32
23: 4 484 62
24: 4 664 112
25: 4 1004 167
26: 4 1231 179
27: 4 1372 209
28: 4 1582 214
29: 5 118 30
30: 5 484 49
31: 5 664 81
32: 5 1004 125
33: 5 1231 142
34: 5 1372 174
35: 5 1582 177
Tree age circumference
> q()squid
Save workspace image? [y/n/c]: n
coli@DESKTOP-J45M1NUM:~$ python
Python 3.9.7 (default, Sep 16 2021, 16:59:08)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.run(['ssh', 'citric', 'cat ~/mydata/data.csv'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'Tree,age,circumference\n1,118,30\n1,484,58\n1,664,87\n1,1004,115\n1,1231,120\n1,1372,142\n1,1582,145\n2,118,33\n2,484,69\n2,664,111\n2,1004,156\n2,1231,172\n2,1372,203\n2,1582,203\n3,118,30\n3,484,51\n3,664,75\n3,1004,108\n3,1231,115\n3,1372,139\n3,1582,140\n4,118,32\n4,484,62\n4,664,112\n4,1004,167\n4,1231,179\n4,1372,209\n4,1582,214\n5,118,30\n5,484,49\n5,664,81\n5,1004,125\n5,1231,142\n5,1372,174\n5,1582,177\n'
>>>
附录
ssh_config配置参考:~/.ssh/config
Host salic
HostName 172.28.24.152
User yukari
IdentityFile ~/.ssh/salic.id_rsa
RemoteForward 3129 localhost:3128
Host citric
HostName 172.28.24.104
User yukari
ProxyJump salic
IdentityFile ~/.ssh/citric.id_rsa
RemoteForward 3129 localhost:3128
LocalForward 8081 172.28.24.104:8080
Host wsl wsl1.succinic wsl2.succinic
User coli
IdentityFile ~/.ssh/coli.id_rsa
Host wsl
HostName localhost
Port 2233
Host wsl1.succinic
HostName 172.28.24.169
Host wsl2.succinic
HostName localhost
Port 2233
HostKeyAlias wsl2.succinic
ProxyJump wsl1.succinic
该配置文件记录了salic、citric两台远程设备,wsl1.succinic、wsl2.succinic两个远程WSL子系统,以及一个本地WSL子系统的ssh配置。
HostKeyAlias的作用是,当HostName冲突(例如同为localhost)时,可以将其指定为两个不同的名称,避免指纹冲突。