Linux学习笔记 #3 使用远程服务器
本文最后更新于:2024年5月6日 下午
在前文的基础上,介绍了远程控制 Linux 服务器的情景,以及在学习中常用的不间断会话服务。
本文大部分内容参考了清华 ZAH 同学的教程,部分参考了 刘遄 老师的《Linux 就该这么学》,菜鸟教程-Linux。
远程控制服务
日常工作中,我们常常会使用远程服务器来进行开发/运维,连接远程服务器需要用到 SecureShell(SSH)。
初次连接
打开本地的终端模拟器,通过如下命令使用 SSH 连接到其他服务器:
1 |
|
在这个例子中,我们尝试以用户名 hewei
登陆服务器 server.hitsz.edu.cn
。服务器可以通过服务器主机名指定(如本例),也可以使用 IP 指定(如 hewei@192.168.1.42
)。SSH 的默认端口是 22,也可以通过 -p port
制定端口。
输入上述命令后,如果成功连接,会提示输入密码,该密码就是远程服务器中对应账户的密码。
本文中由于没有其他服务器,就在本机上用 VirtualBox 创建了一个 Ubuntu 虚拟机作为服务器,获取虚拟机 IP,在主机中用终端连接。参考文章:用vbox搭建Linux服务器。
注意:用本方法需要确保主机接有网线,且虚拟机配置桥接网卡与主机以太网相同。
另一种方法是用公共集群作为临时服务器,可能不支持 SSH,这时候要在远程终端手动激活
sudo service sshd start
。
进入服务器后,可以看到命令行左侧的提示符变成了 hewei@hewei-VirtualBox ~>
,其中 ~
代表在 /home/hewei
用户目录下,>
符号提示远程用户身份,不同服务器可能不一样。输入 logout
可退出远程服务器。
SSH 配置文件
上述连接远程服务器的命令还可以通过修改 SSH 配置文件来简化,进入主机所在的用户文件夹下的 .ssh
文件夹(SSH 密钥所在的文件夹),新建配置文件 config
,添加:
1 |
|
配置完文件后,我们可以使用 ssh test
这样的命令来连接服务器,有助于管理多个服务器的账户。
免登录执行
SSH 的一个经常被忽视的特性是它可以在不登录服务器的状态下直接远程执行命令,例如在配置完 config
后,使用 ssh 别名
命令:
1 |
|
这步操作同样需要输入密码,但不会登录服务器,在主机环境中直接返回结果。
SSH 鉴权
使用 SSH 当然免不了基于密钥对的验证机制,我们只需要将公钥放在服务器上,每次登录时向服务器证明客户端持有对应的私钥。这样就可以避免每次登陆都输入密码了。
在 Git学习笔记 #3 远程仓库使用 中,同样讲述了这个问题,这里假设我们已经生成了密钥对。在本机终端下,可以通过如下命令把公钥传到服务器:
1 |
|
如果本机是 Linux/MacOS,支持 ssh-copy-id
命令,可以用下面这种更简单的方案:
1 |
|
当然,如果已经连上远程终端,也可以在远程直接操作:
1 |
|
如果服务器添加公钥后本机登录仍需要密码,则原因可能是
~/.ssh
目录和~/.ssh/authorized_keys
文件的权限不对,使用以下命令即可:
1
2
$ chmod 700 ~/.ssh
$ chmod 644 ~/.ssh/authorized_keys
scp 文件传输
通常我们需要将文件的工程文件放到服务器上执行,如果采用了 MobaXterm、Xshell 这类增强终端,可以通过拖拽的方式直接实现文件互传。
但如果直接在本机终端中,可以通过如下指令:
1 |
|
此外,使用 scp -r
可以上传文件夹。如果需要更高级的功能,可以考虑使用 rsync
。
此方法也可以用于两台服务器之间传输文件,此时服务器 A 就相当于主机,服务器 B 就相当于远程(B 的 .ssh/authorized_keys
里需要有 A 的公钥,如果没有则需要输入密码)。下面是一个基本的 scp
命令的格式,用于从一个服务器传输文件到另一个服务器:
1 |
|
假设你已经在服务器 1.1.1.1 上,并且你想把本地文件 example.txt
发送到服务器 2.2.2.2 上的 /home/username/
目录,你可以使用以下命令:
1 |
|
这里的参数解释如下:
-P 2222
:指定 SSH 端口号为 2222(注意是大写的P
)。example.txt
:是你想传输的文件名。hewei@2.2.2.2
:目标服务器的用户名和 IP 地址。/home/hewei/
:目标服务器上的目标路径,你想把文件放在哪里。
此外,如果目标服务器使用的是默认的 SSH 端口(22),则可以省略 -P
参数。如果你在执行命令时遇到权限问题,可能需要考虑是否有适当的读写权限或者使用 sudo
。
如果是首次连接到目标服务器,系统可能会要求你验证目标服务器的身份,并询问是否继续连接。此时需要输入 yes
,然后输入目标服务器的用户密码,除非已经设置了 SSH 免密登录。
利用 VS Code 连接
在今年的操作系统实验课上,又学到了一招连接远程服务器的办法,不得不说 VS Code 太强大了!以下的内容需要 Remote - SSH
插件支持。
安装插件后,在 SSH TARGETS
栏选择 Add New
,之后会弹出输入框,输入 初次连接命令,则会弹出提示自动设置 .ssh/config
文件!添加成功后,左侧的 SSH TARGETS
栏就会增加新的远程节点。
在该节点旁边,选中 Connect to Host in New Window
即可打开一个 VS Code 窗口,新打开的窗口会要求你选择目标机器的平台,选择 Linux,按下回车,再确定连接,输入密码,即可连接成功。观察到终端显示的提示符是 190110429@OSLabExecNode1:~$
,成功!
之后,点击 VS Code 侧边栏的资源管理器,就可以直接打开远程的文件夹和文件,更方便编程和调试。此外,同样可以用 SSH 鉴权来简化输入密码的步骤,方法同上。在 VS Code 中按下 Ctrl+反引号
可以快捷打开终端。
预备知识
Vim 入门
通常我们将工程传到服务器上跑时,可能需要修改某些代码或参数,如果没有使用增强终端或者 VSCode Remote 等插件,我们就只能在 CLI 界面进行交互。
要在 CLI 界面简单地编辑⼀个文件,可用的选择大概有 vi, vim, nano 等,通常来说我们选择使用 vim。使用 vim <filename>
命令打开文件进行编辑。
刚打开文件时,vim 处于一个 Normal 模式,在 Normal 模式下按 i
进入 Insert 模式,此时就可以像其他编辑器一样对文件进行编辑。编辑后按下 ESC
键退回到 Normal 模式。
在 Normal 模式下按 :
进入 Command 模式,在这个模式下可以使用命令进行操作,常用命令有::q
退出,:w
保存,:wq
保存并退出。
软件包管理机制
大多数现代类 Unix 操作系统都提供了一个集中的软件包管理机制,以帮助用户搜索、安装和管理软件。而软件通常以包的形式存储在仓库(repository)中,对软件包的使用和管理被称为包管理。而 Linux 包的基本组成部分通常有:共享库、应用程序、服务和文档。
包管理器又称软件包管理系统,它是在电脑中自动安装、配制、卸载和升级软件包的工具组合,在各种系统软件和应用软件的安装管理中均有广泛应用。
几乎每⼀个系统发行版都有它的包管理器,Ubuntu 有 apt
,Arch 有 pacman
,macOS 有 Homebrew
。
包管理器换源
由于众所周知的原因,仓库在国内的访问速度是不佳的,往往需要更换为国内的镜像源,常见的镜像站点有清华的 Tuna,其 Ubuntu 源地址为:https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/ 。
Ubuntu 的软件配置文件时 /etc/apt/sources.list
,首先将系统自带的该文件备份:
1 |
|
此时如果直接用 vim 打开文件,会发现无法进入 Insert 模式,于是需要用:
1 |
|
进入编辑器后,可以进入 Insert 慢慢删除,也可以直接在 Normal 模式下输入 ggyG
全选删除。然后将网站中的配置文件复制进去。
现在就可以使用镜像源下载软件包了,这里以下面要用的 Tmux 为例:
1 |
|
从网络下载资源
如果没有 sudo
权限也想下载软件,或者想下载某些数据集时,就需要内容下载命令 wget
或 curl
,其中前者由系统自带,后者需要用包管理器安装 sudo apt-get install curl
。两个命令的功能有所重叠,总体而言,后者更适合复杂的下载任务,具体用法如下:
基础下载功能:
1
2$ curl -O https://hwcoder.top/index.html # 大写 O,如果缺省则只会打印内容不会下载
$ wget https://hwcoder.top/index.html # 不用参数,直接下载到当前目录下载文件并重命名(指定路径):
1
2$ curl -o rename.html https://hwcoder.top/index.html # 小写 o
$ wget -O rename.html https://hwcoder.top/index.html # 大写 O断点续传:
1
2$ curl -O -C https://hwcoder.top/index.html # 大写 C
$ wget -c https://hwcoder.top/index.html # 小写 c
其中 curl -#
还有进度条功能,支持正则表达式匹配批量下载。wget
支持递归下载,常用于打包下载整个网页。
Tmux 不间断会话服务
命令行的典型使用方式是,打开一个终端窗口(terminal window,以下简称窗口),在里面输入命令。用户与计算机的这种临时的交互,称为⼀次「会话」(session) 。
服务中断
会话的⼀个重要特点是,窗口与其中启动的进程是绑定的——打开窗口,会话开始;关闭窗口,会话结束,会话内部的进程也会随之终止,不管有没有运行结束。
因此,使用 SSH 远程控制服务时,当与远程主机的会话被关闭时,在远程主机上运行的命令也随之被中断。
如果运行某个重要的程序,中途是绝对不能关闭在本地打开的终端窗口或断开网络连接的,甚至连网速的波动都有可能导致任务中断,此时只能重新进行远程连接并重新开始任务。而我们需要在服务器上跑的东西恰恰就是比较占用资源的程序,通常需要执行较长时间,如果因为网速波动而中断就很难受。
分离会话
为了解决这个问题,会话与窗口可以「解绑」:窗口关闭时,会话并不终止,而是继续运行,等到以后需要的时候,再让会话「重新绑定」其他窗口。
Terminal Multiplexer(终端复用器,简称为 Tmux)就是一款能够实现多窗口远程控制的开源服务程序。简单来说就是为了解决网络异常中断或为了同时控制多个远程终端窗口而设计的程序。Unix 系统自带,无需安装。
远程连接服务器后,输入 tmux
进入 Tmux 窗口,窗口下方会出现绿色的一行。在 Tmux 窗口中,输入 tmux detach
命令,就会将当前会话与窗口分离。
1 |
|
上述命令执行后,就会退回到本地终端窗口,但是会话和里面的进程仍然在后台运行。此时可以输入命令查看后台正在运行的 Tmux 会话:
1 |
|
会弹出 0: 1 windows (created Mon Sept 9 20:34:12 2021)
的提示信息,其中 0
表示该窗口标题(默认从 0 开始递增),此外也可以命名窗口:
1 |
|
接入会话
此时就算退出远程连接,会话也会保持运行,可以使用以下命令重新接入某个已存在的会话:
1 |
|
杀死会话
在终端窗口中,如果要彻底杀死一个运行中的会话,需要用到以下命令:
1 |
|
当然,也可以先用 attach
命令接入会话,再按下 Ctrl+D
或者输入 exit
直接退出 Tmux 会话(注意退出与解绑不同)。
管理多窗格
有时候需要同时执行多个程序,并观察输出,就需要多个会话窗口。利用 Tmux 还可以将一个窗口切分为多个(并且独立执行会话,互不干扰)。只要使用如下命令:
1 |
|
在工作中,通过输入命令来切换窗格难免有些麻烦,Tmux 为用户提供了一系列快捷键来执行窗格的切换:先同时按下 Ctrl+B
组合键进入控制模式,松手后:
- 按下
%
表示划分左右两个窗格; - 按下
"
表示划分上下两个窗格; - 按下
<方向键>
表示到上下左右相邻的一个窗格; - 按下
x
表示关闭窗格。