本文参考了鳥哥的《文字介面連線伺服器:SSH 伺服器》。 原文以 CentOS 6 为例讲解,本文根据 Ubuntu 16.04 LTS 的特点做了一些修改。 对于不同的 Linux 发行版,大多数命令是一致的,只在『软件包管理命令』等细节上略有区别。
『SSH (Secure SHell)』是一种用于远程访问 Linux 主机的 CLI 软件。 它通过对通信数据加密与解密,使得本地主机可以『安全地 (securely)』访问远程主机上的『终端 (shell)』,从而使用其资源。
SSH 对数据的加密与解密主要是依靠成对的『公钥 (public key)』和『私钥 (private key)』来实现的:
建立 SSH 连接主要包括以下几步:
/etc/ssh/ssh_host_key
等文件是否存在。如果不存在,则创建这些文件。~/.ssh/known_hosts
中的记录进行对比: # 检查 SSH 服务的状态:
systemctl status ssh
# 如果需要, 安装 SSH 服务端软件:
sudo apt install openssh-server
# 开启 SSH 服务:
sudo systemctl start ssh
sudo systemctl enable ssh
# 再次检查 SSH 服务的状态:
systemctl status ssh
应当返回如下内容(其中 active (running)
为绿色):
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-06-05 12:12:06 CST; 22h ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 841 (sshd)
Tasks: 1 (limit: 19009)
Memory: 6.2M
CGroup: /system.slice/ssh.service
└─841 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
Warning: some journal files were not opened due to insufficient permissions.
# 如果需要,安装 SSH 客户端软件:
sudo apt install openssh-server
登入远程主机上的指定用户:
ssh user@address
# 按提示输入正确的密码后,即可登入远程主机。
或者,登入远程主机后,在远程主机上运行某程序:
# 等程序执行完成后,才切换回本地终端:
ssh user@address do_something
# 不等程序执行完,立即切换回本地终端:
ssh -f user@address do_something
输入 exit
则结束本次 SSH 连接,但一般不会关闭远程主机。若要关闭远程主机,则需输入远程用户密码:
ssh user@address sudo -S poweroff
首先需要在 Windows 主机上安装 SSH 客户端软件,例如 PuTTY。 启动后,在地址栏输入远程 Linux 主机的『IP 地址』和『端口号(默认为 22
)』,然后会弹出一个虚拟终端,在以下提示信息后面输入用户名,并按提示输入密码,即可建立 SSH 连接:
login as:
建立远程连接后,在终端中输入以下命令:
passwd
然后根据提示输入原密码和新密码,这样在下次连接时就需要使用新密码了。
与 ssh
命令类似,登入远程主机上的指定用户:
sftp user@address
# 按提示输入正确的密码后,即可登入远程主机。
# 终端提示符变为:
sftp>
在 sftp>
后,可以输入一般的 shell 命令:
sftp> pwd # 在远程主机上执行
sftp> lpwd # 在本地主机上执行
传输文件需用以下命令:
# 上传到指定远程目录:
sftp> put local_file remote_dir
# 上传到当前远程目录:
sftp> put local_file
# 下载到指定本地目录:
sftp> get remote_file local_dir
# 上传到当前本地目录:
sftp> get local_file
# 上传:
scp local_file user@address:dir
scp -r local_dir user@address:dir
# 下载:
scp user@address:file local_dir
scp -r user@address:dir local_dir
# 指定端口:
scp -r -P port user@address:dir local_dir
默认情况下,每次建立 SSH 连接都需要输入远程主机上指定用户的密码。 当需要频繁建立连接时,我们希望免去这一步骤。 这一需求可以通过『将客户端公钥写入服务端的 ~/.ssh/authorized_keys
文件中』来实现。
首先,在客户端制作密钥:
# 切换到 ~/.ssh 目录:
cd ~/.ssh
# 生成 SSH 密钥:
ssh-keygen # 根据提示
# 先输入文件名(可按一次 [Enter] 以接受默认设置)
# 再输入通行码(可按两次 [Enter] 以接受默认设置)
# 将公钥文件 id_rsa.pub 传送给服务端指定用户:
scp id_rsa.pub user@address:~ # 需要输入服务端密码
然后,在服务端添加授权信息:
# 切换到 ~ 目录
cd ~
# 检查 ~/.ssh 是否存在
ls .ssh
# 如果不存在,建立该目录,并设置权限
mkdir .ssh
chmod 700 .ssh
# 将客户端公钥添加进 authorized_keys
cat id_rsa.pub >> .ssh/authorized_keys
rm id_rsa.pub
# 更改 authorized_keys 的访问权限
chmod 644 .ssh/authorized_keys
作为特例,如果希望能够通过 SSH 免密访问本地主机上的当前用户,只需在本地主机上开启 SSH 服务,并将当前用户的公钥写入自己的 ~/.ssh/authorized_keys
文件。
至此,应当可以从客户端通过 ssh
命令免密登入远程主机上的该用户,或者通过 scp
命令免密上传或下载数据。
⚠️ 若不成功,则需要在每次启动客户端 shell 时开启『认证代理 (authentication agent)』:
eval `ssh-agent` # 启动认证代理
ssh-add ~/.ssh/id_rsa # 加入私钥
ssh-add -l # 列出已加入的私钥
上述命令可置于 ~/.bashrc
或 ~/.zshrc
中,以便每次启动 shell 时自动加载。
执行完以上步骤后,在本地 ~/.ssh/config
文件中添加以下内容,即可免密连接到远程主机上的指定用户:
Host <connection-name>
HostName <remote-address>
Port 22
User <remote-user-name>
IdentityFile ~/.ssh/<private-key-name>
在服务器的 /etc/ssh/sshd_config
文件中加入以下两行:
Port 22 # 默认端口
Port 1024 # 新开端口
并重启 SSH 服务:
sudo service sshd restart
在客户端选择目标端口:
ssh username@hostname_or_ipaddress # 通过默认端口连接
ssh -p 1024 username@hostname_or_ipaddress # 通过特定端口连接
使用场景:借助 SSH 在远程主机启动某个(耗时较长的)任务后,允许当前 SSH 连接挂起或断开。
# nohup := no hang up
nohup command [options] # 在远程主机的前台运行任务
nohup command [options] & # 在远程主机的后台运行任务