← 返回网站实战路线

第 1 步 · 环境与服务器 · 5-7 天

Linux 快速使用与实战

先准备网站运行环境,掌握目录、权限、进程、端口、日志和软件安装等高频操作。

3 个阶段本阶段产出:一台能够登录、安装软件并安全运行服务的 Linux 环境。

本阶段思路

学到刚好能推动网站进入下一步

理解用途

先知道它位于哪里

明确当前技术在网站中的职责,以及它与上一步、下一步怎样连接。

完成实战

所有练习进入同一项目

不做无关的小例子,直接完善正在搭建的网站。

按结果验收

达到交付标准再继续

以可运行、可检查的结果判断是否完成,而不是以看完多少教程判断。

从第一个命令开始

按顺序完成 Linux 服务器基础

以下步骤以 Ubuntu Server 为例。代码块中的 IP、用户名和路径需要按你的服务器替换;每次只完成一步,确认预期结果后再继续。

第 01 步

从本地电脑连接服务器

专业解释

SSH(Secure Shell)远程登录

大白话

SSH 就像一条加密的远程控制通道。你在自己电脑的终端输入命令,实际操作的是远处的 Linux 服务器。

这一节要做到

准备服务器 IP、用户名和密码,在本地终端完成第一次登录。

按顺序执行bash
# 下面这条命令在“自己的电脑”执行,不是在服务器执行
# 把 root 和 203.0.113.10 换成服务商提供的用户名与公网 IP
ssh root@203.0.113.10

# 如果 SSH 不是默认的 22 端口,使用 -p 指定端口
ssh -p 2222 root@203.0.113.10

# 第一次连接会询问是否信任主机,核对 IP 后输入 yes
# 随后输入密码。输入密码时屏幕不会显示星号,这是正常现象

# 完成操作后退出服务器
exit

命令说明

  • ssh 是客户端命令
  • root@IP 中 @ 前面是服务器用户,后面是服务器地址
  • -p 只在服务商修改了 SSH 端口时使用
  • exit 会结束远程会话并回到自己的电脑

完成后的结果

登录后命令提示符会发生变化,通常会显示类似 root@server:~#。执行 exit 后返回本地提示符。

第 02 步

确认当前身份和服务器环境

专业解释

运行环境识别与系统基线

大白话

先弄清“我是谁、我在哪、这是什么系统”,再安装软件。很多命令失败只是因为系统版本、CPU 架构或用户权限不同。

这一节要做到

确认当前用户、主机名、Ubuntu 版本、CPU 架构、时间和当前目录。

按顺序执行bash
# 当前登录用户
whoami

# 当前所在目录
pwd

# 主机名、操作系统、内核与架构
hostnamectl

# 查看 Ubuntu/Debian 发行版信息
cat /etc/os-release

# 只查看 CPU 架构:常见为 x86_64 或 aarch64
uname -m

# 查看系统时间和时区
timedatectl

# 查看最近执行过的命令
history | tail -20

命令说明

  • whoami 用来避免把普通操作误认为 root 操作
  • pwd 是执行复制、移动和删除前最值得养成的习惯
  • /etc/os-release 是标准系统信息文件
  • uname -m 决定下载 amd64 还是 arm64 软件

完成后的结果

你能记录系统版本、架构、主机名、当前用户和时区,并知道自己当前位于哪个目录。

第 03 步

创建日常使用的普通用户

专业解释

最小权限原则(Principle of Least Privilege)

大白话

root 拥有整台服务器的最高权限,输错一个命令就可能破坏系统。平时使用普通用户,需要管理系统时才临时加 sudo。

这一节要做到

创建 deploy 用户,允许它使用 sudo,并验证新用户可以登录。

按顺序执行bash
# 创建 deploy 用户,按照提示设置密码
adduser deploy

# 把 deploy 追加到 sudo 用户组
# -a 表示追加,-G 表示附加用户组;不要漏掉 -a
usermod -aG sudo deploy

# 查看用户 ID、主组和附加组
id deploy

# 临时切换为 deploy,并加载它的登录环境
su - deploy

# 确认当前已经是 deploy
whoami

# 测试 sudo 权限;会要求输入 deploy 的密码
sudo whoami

# 返回上一位用户
exit

命令说明

  • adduser 会创建用户、家目录和基础配置
  • sudo 组中的用户可以临时执行管理命令
  • su - 中的短横线表示加载目标用户的完整登录环境
  • sudo whoami 预期输出 root,但当前会话仍是 deploy

完成后的结果

id deploy 的输出包含 sudo 组;切换后 whoami 输出 deploy,sudo whoami 输出 root。

第 04 步

配置 SSH 密钥登录

专业解释

非对称密钥认证(Public Key Authentication)

大白话

本地保管一把不能外传的“私钥”,服务器只保存对应的“公钥”。登录时双方验证是否匹配,不需要把服务器密码反复发送。

这一节要做到

在本地创建密钥,把公钥安装给 deploy,并用新终端验证登录。

按顺序执行bash
# 第 1 部分:在“自己的电脑”执行
# 创建现代 ED25519 密钥;提示保存位置时可直接回车
ssh-keygen -t ed25519 -C "deploy-webapp"

# 将公钥安装到服务器的 deploy 用户
ssh-copy-id deploy@203.0.113.10

# 第 2 部分:打开一个新的本地终端进行验证
ssh deploy@203.0.113.10

# 登录后确认身份
whoami

# 查看公钥目录权限
ls -ld ~/.ssh
ls -l ~/.ssh/authorized_keys

命令说明

  • ssh-keygen 生成私钥和 .pub 公钥两个文件
  • ssh-copy-id 只复制公钥,不会上传私钥
  • ~ 表示当前用户的家目录,例如 /home/deploy
  • authorized_keys 保存允许登录此用户的公钥

完成后的结果

新终端能够以 deploy 登录;如果私钥设置了口令,只需输入私钥口令而不是服务器用户密码。

选择编辑器

Vim 与 Nano 常用快捷键

两者任选一种完成练习。Nano 更容易入门,Vim 更适合频繁使用终端编辑。

模态文本编辑器(Modal Text Editor)

Vim 把“输入文字”和“操作文字”分成不同模式。记不清当前模式时先按 Esc,再执行保存、退出或移动命令。

打开与保存示例bash
# 在终端安装并打开文件
sudo apt install -y vim
cp app.conf app.conf.before-vim
vim app.conf

# 进入 Vim 后:按 i 开始输入
# 输入完成后:按 Esc 回到普通模式
# 输入 :wq 并回车:保存并退出

# 退出后比较修改
diff -u app.conf.before-vim app.conf
i / a / o macOS: i / a / o
进入插入模式:当前位置前、当前位置后、下方新建一行。
Esc macOS: Esc
回到普通模式;不知道当前状态时先按它。
:w / :q / :wq macOS: :w / :q / :wq
保存、退出、保存并退出,输入后按回车。
:q! macOS: :q!
放弃上次保存后的所有修改并强制退出。
h j k l macOS: h j k l
普通模式下向左、下、上、右移动。
gg / G / 10G macOS: gg / G / 10G
跳到首行、末行或第 10 行。
dd / yy / p macOS: dd / yy / p
删除整行、复制整行、粘贴。数字前缀可操作多行。
u / Ctrl+r macOS: u / Control+r
撤销与重做。Mac 终端中使用 Control,不是 Command。
/词 / n / N macOS: /词 / n / N
搜索,并跳到下一个或上一个结果。
:set number macOS: :set number
显示行号;使用 :set nonumber 关闭。
第 07 步

理解文件所有者和权限

专业解释

自主访问控制(DAC)与 rwx 权限模型

大白话

每个文件都规定“主人、同组成员、其他人”分别能不能读、写、执行。权限太小会运行失败,权限太大则任何人都可能修改。

这一节要做到

能读懂 ls -l,掌握 chown、chmod,并为网站目录设置合理权限。

按顺序执行bash
# 创建网站目录结构
sudo mkdir -p /srv/webapp/{releases,shared,logs,backups}

# deploy 是所有者,www-data 是 Web 服务常用用户组
sudo chown -R deploy:www-data /srv/webapp

# 目录权限 750:所有者 rwx,组 r-x,其他人无权限
sudo chmod 750 /srv/webapp
sudo chmod 750 /srv/webapp/{releases,shared,logs,backups}

# 创建环境配置并限制权限
touch /srv/webapp/shared/app.env

# 文件权限 640:所有者读写,组只读,其他人无权限
chmod 640 /srv/webapp/shared/app.env

# 查看权限、所有者和用户组
ls -ld /srv/webapp /srv/webapp/shared
ls -l /srv/webapp/shared/app.env

# 查看当前用户所属的组
id

命令说明

  • r=4 读取,w=2 写入,x=1 执行;相加得到数字权限
  • 目录的 x 表示可以进入和访问其内容
  • chown user:group 同时设置所有者和用户组
  • -R 表示递归,使用前必须确认目标目录范围

完成后的结果

app.env 显示类似 -rw-r-----,网站目录显示类似 drwxr-x---,所有者为 deploy,组为 www-data。

第 08 步

更新软件索引并安装常用工具

专业解释

APT 软件包管理与依赖解析

大白话

APT 像服务器的软件商店。update 刷新“商品目录”,install 才真正安装,upgrade 会升级已经安装的软件。

这一节要做到

更新索引并安装 curl、git、unzip、rsync、tree 等后续会使用的工具。

按顺序执行bash
# 刷新可用软件版本信息,不会直接升级软件
sudo apt update

# 查看有哪些软件可以升级
apt list --upgradable

# 安装网站部署常用工具
sudo apt install -y curl git unzip zip rsync tree ca-certificates

# 检查命令是否存在及其版本
curl --version
git --version
rsync --version

# 搜索软件包
apt search nginx

# 查看软件包说明、版本和依赖
apt show nginx

# 查看某个包是否已经安装
dpkg -l | grep curl

命令说明

  • apt update 只更新索引
  • -y 自动回答安装确认,只对你已经确认的软件列表使用
  • apt search 搜包,apt show 看详情
  • dpkg -l 查看本机包状态

完成后的结果

安装过程无错误,curl、git 和 rsync 的版本命令能够正常输出。

第 09 步

查看进程、CPU、内存和磁盘

专业解释

进程调度与系统资源观测

大白话

程序运行后就是进程。网站变慢或崩溃时,先看是谁占用了 CPU、内存或磁盘,不要第一反应就重启服务器。

这一节要做到

掌握 ps、top、free、df、du、uptime 和安全终止进程。

按顺序执行bash
# 查看系统已运行多久,以及 1/5/15 分钟平均负载
uptime

# 实时查看 CPU 和内存,按 q 退出
top

# 查看内存;重点看 available,不只看 free
free -h

# 查看各文件系统磁盘使用率
df -h

# 查看 /var 下一级目录占用并按大小排序
sudo du -h --max-depth=1 /var | sort -h

# 列出全部进程并搜索 ssh
ps aux | grep '[s]shd'

# 启动一个 300 秒的练习进程
sleep 300 &

# jobs 查看当前终端后台任务,ps 获取 PID
jobs
ps aux | grep '[s]leep 300'

# 先发送 TERM,让程序有机会正常退出
kill PID

# 再确认进程已经消失
ps -p PID

命令说明

  • load average 要结合 CPU 核数判断,不是简单的百分比
  • free -h 中 available 更接近还能使用的内存
  • df 看整个分区,du 找具体大目录
  • kill 默认发送 TERM;只有无响应时才最后考虑 kill -9

完成后的结果

你能找到 sleep 的 PID,用普通 kill 结束它,并能指出服务器磁盘与可用内存情况。

第 10 步

把程序交给 systemd 长期运行

专业解释

服务管理器、守护进程与生命周期管理

大白话

直接在 SSH 窗口启动程序,退出后它可能停止。systemd 像管理员,负责启动、停止、自动重启、开机启动和收集日志。

这一节要做到

创建一个安全的练习服务,掌握 systemctl 和 journalctl 的完整操作顺序。

按顺序执行bash
# 安装 Python 只用于启动练习 HTTP 服务
sudo apt install -y python3

# 准备静态文件
mkdir -p /srv/webapp/releases/demo
echo 'Linux service is running' > /srv/webapp/releases/demo/index.html

# 创建 systemd 服务文件
sudo nano /etc/systemd/system/webapp-demo.service

# 在 nano 中写入以下内容(不要把这一段当作终端命令执行)
# [Unit]
# Description=Webapp demo HTTP service
# After=network.target
#
# [Service]
# Type=simple
# User=deploy
# WorkingDirectory=/srv/webapp/releases/demo
# ExecStart=/usr/bin/python3 -m http.server 8080 --bind 127.0.0.1
# Restart=on-failure
#
# [Install]
# WantedBy=multi-user.target

# 让 systemd 重新读取服务文件
sudo systemctl daemon-reload

# 立即启动并设置开机自动启动
sudo systemctl enable --now webapp-demo

# 查看状态;--no-pager 避免进入分页界面
sudo systemctl status webapp-demo --no-pager

# 查看最近 50 行日志
sudo journalctl -u webapp-demo -n 50 --no-pager

# 持续跟踪日志,按 Ctrl+C 退出
sudo journalctl -u webapp-demo -f

# 常用控制命令
sudo systemctl restart webapp-demo
sudo systemctl stop webapp-demo
sudo systemctl start webapp-demo

命令说明

  • Unit 描述依赖,Service 描述怎样运行,Install 描述开机启动目标
  • User=deploy 避免服务以 root 运行
  • --bind 127.0.0.1 只允许服务器本机访问
  • 修改 .service 后先 daemon-reload,再 restart

完成后的结果

systemctl status 显示 active (running),服务重启后仍可运行,journalctl 能看到请求或启动日志。

第 11 步

检查端口并测试 HTTP 服务

专业解释

Socket 监听、回环地址与 HTTP 请求诊断

大白话

程序运行不代表网站能访问。还要确认它监听了哪个 IP、哪个端口,并从最近的位置一层一层测试。

这一节要做到

使用 ss 和 curl 验证 8080 服务,并掌握固定的网络排障顺序。

按顺序执行bash
# 确保练习服务正在运行
sudo systemctl start webapp-demo

# 查看 TCP 监听:-l 监听,-n 数字,-t TCP,-p 进程
sudo ss -lntp

# 只筛选 8080 端口
sudo ss -lntp | grep ':8080'

# 从服务器本机请求服务,同时显示响应头
curl -i http://127.0.0.1:8080/

# 只查看响应头
curl -I http://127.0.0.1:8080/

# 显示连接和请求过程,适合排障
curl -v http://127.0.0.1:8080/

# 查看本机 IP 和默认路由
ip addr
ip route

# 查询域名解析结果;把域名替换成自己的
getent hosts example.com

命令说明

  • 127.0.0.1 是回环地址,只能从服务器自己访问
  • 0.0.0.0 表示监听全部 IPv4 接口,暴露范围更大
  • ss 证明端口是否监听,curl 证明 HTTP 是否正常响应
  • 排障顺序是服务状态 → 日志 → 监听端口 → 本机 curl → 防火墙 → DNS

完成后的结果

ss 显示 127.0.0.1:8080,curl 返回 HTTP 200 和 Linux service is running。

第 12 步

配置防火墙的最小开放端口

专业解释

主机防火墙与入站访问控制

大白话

防火墙像服务器门口的保安。网站通常只需要 SSH、HTTP 和 HTTPS 三类入口,数据库和 Go API 留在服务器内部。

这一节要做到

先允许 SSH,再启用 UFW,只开放 22、80 和 443。

按顺序执行bash
# 查看 UFW 当前状态
sudo ufw status verbose

# 第一条必须先允许 SSH,避免把自己锁在服务器外
sudo ufw allow OpenSSH

# 允许网站的 HTTP 和 HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# 再次确认规则中已经包含 OpenSSH
sudo ufw status numbered

# 确认 SSH 已允许后才启用防火墙
sudo ufw enable

# 查看最终状态和规则
sudo ufw status verbose

# 如果误加规则,可先查看编号,再按编号删除
sudo ufw status numbered
# sudo ufw delete 规则编号

命令说明

  • OpenSSH 是 UFW 内置的 SSH 应用规则
  • 80 是 HTTP,443 是 HTTPS
  • 8080 练习服务没有开放,因此公网不能直接访问
  • 云服务器还可能有服务商安全组,需要同时检查

完成后的结果

UFW 显示 active,并允许 OpenSSH、80/tcp 和 443/tcp;当前 SSH 会话与新的 SSH 会话都能连接。

第 13 步

按顺序查看日志并定位故障

专业解释

可观测性、日志过滤与故障域缩小

大白话

遇到错误时不要乱改配置。先看服务说了什么,再确认端口和请求。每查一步,都把问题范围缩小一点。

这一节要做到

掌握 journalctl、tail、grep 和系统日志的常用排障组合。

按顺序执行bash
# 查看服务本次启动以来的日志
sudo journalctl -u webapp-demo -b --no-pager

# 只看最近 100 行
sudo journalctl -u webapp-demo -n 100 --no-pager

# 查看今天的日志
sudo journalctl -u webapp-demo --since today --no-pager

# 查看本次开机的错误级别系统日志
sudo journalctl -p err -b --no-pager

# 实时追踪普通日志文件;按 Ctrl+C 停止
tail -f /var/log/syslog

# 搜索 error,忽略大小写并显示行号
grep -ni 'error' /var/log/syslog

# 查看内核近期信息,常用于磁盘、网络、内存问题
sudo dmesg -T | tail -50

# 一套固定的网站排障顺序
sudo systemctl status webapp-demo --no-pager
sudo journalctl -u webapp-demo -n 50 --no-pager
sudo ss -lntp | grep ':8080'
curl -i http://127.0.0.1:8080/

命令说明

  • -u 按服务筛选,-b 限定本次开机,--since 限定时间
  • tail -f 会持续等待新日志,必须用 Ctrl+C 退出
  • 先查服务内部,再查网络外部,可以避免无目的修改
  • 记录错误发生时间能大幅减少日志搜索范围

完成后的结果

你能够说明故障发生在“服务未启动、服务报错、端口未监听、HTTP 返回异常”中的哪一层。

第 14 步

上传文件、增量部署和备份

专业解释

安全文件传输、增量同步与归档

大白话

把本地构建结果传到服务器,少量文件可用 scp;重复部署用 rsync 只传变化;备份用 tar 打包。它们都可以走 SSH 加密通道。

这一节要做到

从本地上传文件到 releases,使用 rsync 预演同步,并在服务器创建备份。

按顺序执行bash
# 第 1 部分:在“自己的电脑”执行
# 上传单个文件
scp index.html deploy@203.0.113.10:/srv/webapp/releases/demo/

# 上传整个目录;-r 表示递归
scp -r dist deploy@203.0.113.10:/srv/webapp/releases/

# rsync 先预演:-a 保留结构,-v 显示过程,-z 压缩,-n 不实际修改
rsync -avzn dist/ deploy@203.0.113.10:/srv/webapp/releases/frontend/

# 确认预演结果后去掉 n,执行同步
rsync -avz dist/ deploy@203.0.113.10:/srv/webapp/releases/frontend/

# 第 2 部分:登录服务器后执行
ssh deploy@203.0.113.10

# 将 demo 目录打包备份;日期会写入文件名
tar -czf /srv/webapp/backups/demo-$(date +%F).tar.gz   -C /srv/webapp/releases demo

# 查看压缩包内容,不解压
tar -tzf /srv/webapp/backups/demo-$(date +%F).tar.gz

# 查看备份大小
ls -lh /srv/webapp/backups/

命令说明

  • scp 适合简单复制,rsync 适合重复部署
  • 源目录 dist/ 末尾斜杠表示同步目录里面的内容
  • rsync -n 是预演,不会真正修改目标
  • tar -C 先切换目录,可避免压缩包包含很长的绝对路径

完成后的结果

服务器 releases 中出现上传文件,rsync 预演与执行结果一致,backups 中有可列出内容的日期压缩包。

第 15 步

完成服务器基础交付检查

专业解释

服务器初始化基线与可重复交付

大白话

最后不是“命令都看过了”,而是确认换一个终端、重启一次服务、出现一次错误时,你仍然知道怎么处理。

这一节要做到

执行最终检查并记录结果,为下一步安装 MySQL 做好准备。

按顺序执行bash
# 身份与系统
whoami
hostnamectl

# 网站目录与权限
ls -ld /srv/webapp /srv/webapp/*
ls -l /srv/webapp/shared/app.env

# 服务、日志与端口
sudo systemctl is-enabled webapp-demo
sudo systemctl is-active webapp-demo
sudo journalctl -u webapp-demo -n 20 --no-pager
sudo ss -lntp | grep ':8080'
curl -i http://127.0.0.1:8080/

# 资源和防火墙
df -h
free -h
sudo ufw status verbose

# 可用更新
sudo apt update
apt list --upgradable

# 备份
ls -lh /srv/webapp/backups/

命令说明

  • 每项检查都应该有可观察结果
  • is-enabled 检查开机启动,is-active 检查当前运行
  • 只有本机能访问 8080 是当前阶段的正确状态
  • 把系统版本、用户、目录、服务、端口和恢复方法写入项目文档

完成后的结果

deploy 可通过密钥登录;目录权限正确;服务 active 且 enabled;8080 仅本机监听;UFW 只开放必要入口;备份可以读取。

官方资料

Ubuntu Server 官方文档

遇到系统配置、网络、软件包或安全问题时,以发行版官方文档为最终参考。

https://ubuntu.com/server/docs打开官网 ↗