Linux 运维基础

本文面向没有 Linux 运维经验,但需要独立完成服务器日常维护的开发人员

阅读完成后,应至少能够完成以下工作:

  • 在 Linux 中查找、复制、移动、编辑文件
  • 理解 Linux 用户与文件权限
  • 查看 CPU、内存、磁盘和进程状态
  • 上传、下载和压缩服务器文件
  • 安装软件
  • 查看并管理后台服务
  • 查看日志、监听端口和网络状态
  • 完成简单的 Nginx 配置及证书更换
  • 使用 Docker 启停、更新和排查容器

文中的命令主要适用于常见的 Ubuntu/Debian、CentOS/RHEL/Rocky Linux 等发行版。不同发行版之间可能存在少量差异。


基础知识

关键目录

Linux 没有 Windows 中的 C:D: 等盘符概念,整个文件系统从根目录 / 开始组织。

例如:

/
├── bin
├── boot
├── dev
├── etc
├── home
├── root
├── tmp
├── usr
├── var
└── ...

日常运维中最常接触以下目录:

目录用途
/整个文件系统的根目录
/rootroot 用户的家目录
/home普通用户的家目录,例如 /home/zhangsan
/etc系统及软件的配置文件
/var经常发生变化的数据,如日志、缓存、数据库数据
/var/log系统和部分软件的日志
/tmp临时文件,系统或程序可能自动清理
/usr大量系统程序、库和共享资源
/opt第三方软件常用安装目录
/bin/usr/bin常用可执行程序
/sbin/usr/sbin系统管理程序
/dev硬盘、终端等设备对应的特殊文件
/proc内核提供的进程和系统信息,并不是真正存储在硬盘上的普通文件
/run系统运行期间产生的 PID、Socket 等临时运行数据

实际部署应用时,并不存在一个强制要求的统一目录。

例如可以根据团队规范使用:

/opt/myapp
/srv/myapp
/www/wwwroot/myapp
/home/app/myapp

但不建议没有规划地把应用、日志、上传文件和数据库全部堆放在 /root

常见路径写法

Linux 使用 / 分隔目录:

/etc/nginx/nginx.conf

其中:

  • /:根目录
  • .:当前目录
  • ..:上一级目录
  • ~:当前用户的家目录

例如:

cd ..
cd /etc/nginx
cd ~/project

可以使用:

pwd

查看当前所在目录。


基础操作

与 Windows 类似,在 Linux 上输入的命令通常对应某个程序,由 Shell 查找并执行。

常见 Shell 是 Bash。

例如:

ls

实际上是在执行系统中的 ls 程序。

可以通过:

which ls

查看程序的位置。

文件与路径

cd

进入某个目录:

cd /etc/nginx

返回上一级:

cd ..

返回当前用户家目录:

cd ~

返回上一次所在目录:

cd -

ls

列出目录中的文件:

ls

运维中常用:

ls -lah

其中:

  • -l:显示详细信息
  • -a:包含隐藏文件
  • -h:使用 KB、MB、GB 等易读单位显示文件大小

很多 Linux 环境会配置:

ll

作为 ls -l 或类似命令的别名,但 ll 并不是 Linux 标准命令,并非所有服务器都存在


mv

移动或重命名文件。

移动:

mv a/b.txt b/

表示将:

a/b.txt

移动到:

b/

重命名:

mv old.txt new.txt

目录也可以使用相同方式移动:

mv old_dir new_dir

cp

复制文件:

cp a/b.txt b/

复制目录需要添加 -r

cp -r a/ b/

需要保留权限、时间等信息时,也经常使用:

cp -a source/ target/

rm

删除文件:

rm a.txt

删除目录及其内容:

rm -r directory/

强制递归删除:

rm -rf directory/

其中:

  • -r:递归处理目录
  • -f:忽略不存在的文件,并尽量不进行交互确认

rm -rf 是 Linux 运维中最危险的常用命令之一。

Linux 命令行删除文件后通常没有类似 Windows 回收站的恢复流程,特别是 root 用户执行错误路径时可能造成严重事故。

例如绝不能随意执行:

rm -rf /

现代 GNU rm 通常会对直接删除 / 做额外保护,但不能依赖这一保护防止所有误操作。

执行危险命令之前建议先:

ls /准备删除的路径

确认路径正确,再执行删除。

另外,不添加 -f 并不意味着 rm 一定会逐个询问是否删除。是否提示确认还取决于文件权限、Shell 别名以及是否使用了 -i 等参数。

希望明确要求确认可以使用:

rm -i file

rmdir

删除空目录:

rmdir directory

只能删除空目录,因此实际运维中使用较少。


mkdir

创建目录:

mkdir project

如果父目录不存在:

mkdir -p /opt/project/data

-p 会自动创建缺失的父目录。


touch

创建一个空文件:

touch app.log

如果文件已经存在,则默认更新它的访问时间和修改时间,不会清空文件内容。


find

按照条件查找文件:

find /opt -name "app.log"

查找 .log 文件:

find /var/log -name "*.log"

查找大于 500 MB 的文件:

find / -type f -size +500M 2>/dev/null

find 在排查服务器磁盘空间问题时非常实用。


基础文本处理

cat

直接将文本文件全部输出到控制台:

cat app.conf

适合比较短的配置文件。

对于几百 MB 甚至数 GB 的日志,不应直接使用 cat 输出全部内容。


less

分页查看文件:

less app.log

常用操作:

  • / :滚动
  • PageUp / PageDown:翻页
  • /ERROR:向下搜索 ERROR
  • n:继续查找
  • q:退出

对于比较大的文本文件,less 通常比 cat 更合适。


head / tail

查看文件头部:

head app.log

默认前 10 行。

查看前 100 行:

head -n 100 app.log

查看最后 100 行:

tail -n 100 app.log

持续追踪日志:

tail -f app.log

查看最后 100 行并持续追踪:

tail -n 100 -f app.log

也可以简写为:

tail -100f app.log

Ctrl+C 停止。


grep

从文件或命令输出中筛选包含指定内容的行。

从文件搜索:

grep ERROR app.log

忽略大小写:

grep -i error app.log

显示行号:

grep -n ERROR app.log

递归搜索某目录:

grep -R "database.password" /opt/myapp/

从上一条命令的输出中筛选:

docker logs app 2>&1 | grep ERROR

原本也可以写成:

cat app.log | grep ERROR

但直接:

grep ERROR app.log

更加简单。


用户与权限管理

权限控制

使用:

ls -l

可能看到:

-rwxr-xr-- 1 user developers 1250 Aug 21 10:00 start.sh

其中:

-rwxr-xr--

共 10 个字符。

第一个字符表示文件类型,例如:

-    普通文件
d    目录
l    符号链接

剩余 9 位:

rwx r-x r--
│   │   │
│   │   └─ 其他用户
│   └───── 所属用户组
└───────── 文件所有者

其后的:

user developers

分别表示:

  • 文件所有者
  • 文件所属组

r、w、x

对于普通文件:

  • r:读取文件内容
  • w:修改文件
  • x:执行文件

对于目录,含义有所不同:

  • r:读取目录项,可以列出目录中的文件名
  • w:可以修改目录项,例如创建、删除或重命名文件
  • x:可以进入、穿过目录并访问其中的文件

目录操作经常需要多种权限组合,因此不能简单理解为“有 w 就一定能修改目录中的所有文件”。

例如:

./start.sh

如果脚本没有执行权限,可能得到:

Permission denied

三组权限

第一组:

rwx

属于文件所有者。

第二组:

rwx

属于文件所属用户组中的用户。

第三组:

rwx

属于既不是所有者、也不属于前述权限匹配范围的其他用户。

“other” 并不是“访客账户”,而是 Linux 权限模型中的其他用户类别。

权限分级示意

root 是 Linux 超级用户,在传统文件权限模型中通常可以绕过大量普通权限限制,因此应谨慎使用。


chmod 指令

chmod 用于修改文件权限。

权限数字:

r = 4
w = 2
x = 1

因此:

rwx = 4 + 2 + 1 = 7
r-x = 4 + 1 = 5
rw- = 4 + 2 = 6
r-- = 4

常见权限:

777

chmod 777 a.sh

权限:

rwxrwxrwx

所有用户都可以读取、修改和执行。

生产环境中一般不建议为了“解决权限问题”直接使用 777


755

chmod 755 a.sh

得到:

rwxr-xr-x

常用于程序和目录:

  • 所有者:读、写、执行
  • 其他用户:读、执行

644

chmod 644 a.txt

得到:

rw-r--r--

常用于普通配置文件:

  • 所有者:读、写
  • 其他用户:只读

添加执行权限

chmod +x start.sh

更明确地表示所有用户类别增加执行权限可以写:

chmod a+x start.sh

只给所有者增加执行权限:

chmod u+x start.sh

其中:

  • u:user,所有者
  • g:group,所属组
  • o:other,其他用户
  • a:all,全部

递归修改

例如:

chmod -R 755 directory/

会递归修改目录中所有内容。

需要谨慎使用,因为文件和目录通常不应该具有完全相同的权限


chown

chmod 修改“可以做什么”,而 chown 修改“文件属于谁”。

例如:

chown nginx app.conf

修改所有者。

同时修改所有者和所属组:

chown nginx:nginx app.conf

递归修改:

chown -R nginx:nginx /var/www/app

排查 Nginx、Java、PHP 等程序的 Permission denied 时,除了 chmod,还应检查文件所有者和所属组。


用户常用操作

Linux 输入密码时,终端通常不会显示任何字符甚至 *,这是正常现象,输入和退格仍然有效。

查看当前有效用户

whoami

查看登录会话中的用户

who am i

它与 whoami 并不完全相同。

例如使用 sudosu 等改变身份后,两者可能显示不同的信息。


切换用户

su root

更常用:

su -

或者:

su - username

- 会同时加载目标用户的登录环境。


sudo

以 root 或其他授权身份执行单条命令:

sudo systemctl restart nginx

通常比长期直接登录 root 更安全。


资源管理

服务器出现:

  • 网站打不开
  • 接口突然变慢
  • 服务被系统杀掉
  • 数据库异常
  • 无法写入文件

等问题时,CPU、内存、磁盘和进程状态通常是第一批需要检查的信息。


top 指令

top

类似 Windows 的任务管理器,可以实时查看:

  • CPU 使用率
  • 内存使用量
  • Load Average
  • 进程
  • 每个进程的 CPU / 内存占用

top 指令示意图

常见字段:

PID
USER
%CPU
%MEM
COMMAND

按:

q

退出。

如果系统安装了 htop,其界面通常更加友好:

htop

free 指令

查看内存:

free -h

例如:

               total        used        free      shared  buff/cache   available
Mem:            15Gi        5Gi         2Gi        ...

日常判断是否真的“内存不足”,通常更关注:

available

而不是只看 free

Linux 会尽可能利用空闲内存进行缓存,因此看到大量内存被使用不一定表示内存紧张。


df 指令

查看各文件系统的磁盘空间:

df -h

df指令示意

常见重点:

Filesystem
Size
Used
Avail
Use%
Mounted on

例如:

/dev/sda1       100G    95G    5G   95% /

表示挂载到 / 的文件系统已经使用 95%。

df 只能告诉我们哪个文件系统快满了,不能直接告诉我们具体哪个目录占用了空间。


du 指令

找到真正占用空间的目录通常使用:

du -sh /var/*

查看 /var 下一级目录大小。

例如:

du -sh /var/* | sort -h

按大小排序。

查看当前目录:

du -sh ./*

这是排查磁盘空间不足最常使用的组合之一:

df -h
du -sh /*
du -sh /var/*

逐层缩小范围。


ps 指令

查看进程:

ps aux

搜索 Java:

ps aux | grep java

也经常使用:

ps -ef | grep java

更直接的方法是:

pgrep -af java

kill 指令

正常结束某个进程:

kill PID

例如:

kill 12345

如果程序无法正常结束,最后才考虑:

kill -9 12345

-9 会发送 SIGKILL,程序无法自行清理资源,因此不应该把 kill -9 当作默认停止程序的方法


进阶使用

文件传输

FTP / SFTP

传统 FTP 可以通过 FTP 服务端和客户端管理服务器文件,但普通 FTP 默认不会加密登录密码和传输内容。

在现代服务器运维中,如果已经使用 SSH,通常优先使用:

SFTP

SFTP 基于 SSH,与 FTP 是不同的协议。

很多 SSH 客户端,如:

  • FinalShell
  • Xshell + Xftp
  • MobaXterm
  • Termius

等都会提供图形化 SFTP 文件管理能力。

只要服务器 SSH 可正常登录,通常无需额外部署 FTP 服务。


scp

scp 通过 SSH 传输文件。

从服务器下载:

scp root@192.168.1.10:/root/xx.tar ./

如果 SSH 使用非 22 端口:

scp -P 9922 root@192.168.1.10:/root/xx.tar ./

表示:

  1. 使用 root 用户
  2. 连接 192.168.1.10
  3. SSH 端口为 9922
  4. 下载 /root/xx.tar
  5. 保存到本机当前目录

上传文件:

scp ./app.jar root@192.168.1.10:/opt/app/

递归传输目录:

scp -r ./project root@192.168.1.10:/opt/

注意:

-P

是大写。


wget

直接从 URL 下载:

wget https://example.com/file.tar.gz

指定文件名:

wget -O app.tar.gz https://example.com/download

wget指令示意


curl

curl 同样可以下载文件:

curl -O https://example.com/file.tar.gz

跟随 HTTP 重定向:

curl -L -O https://example.com/file.tar.gz

但在开发和运维中,curl 更常用于测试 HTTP 接口。

例如:

curl http://127.0.0.1:8080/health

POST JSON:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"test"}' \
  http://127.0.0.1:8080/api

因此:

  • 简单下载:wget 非常方便
  • HTTP 接口测试:通常使用 curl

文件压缩解压

tar 指令

tar 本质上首先是一个归档工具,可以再配合 gzip、xz 等压缩算法使用。

常用选项

  • -c:创建归档
  • -x:解开归档
  • -f:指定归档文件
  • -z:使用 gzip
  • -J:使用 xz
  • -v:输出正在操作的文件
  • -C:指定目标目录

解压 tar.gz

tar -xzvf app.tar.gz

通常不想显示大量文件名时:

tar -xzf app.tar.gz

解压 tar

tar -xvf app.tar

创建 tar.gz

tar -czvf archive.tar.gz /path/to/directory

解压到指定目录

tar -xzf app.tar.gz -C /opt/app/

查看压缩包内容但不解压

tar -tzf app.tar.gz

zip / unzip

部分项目也使用 ZIP:

unzip app.zip

压缩:

zip -r app.zip app/

如果系统未安装:

Ubuntu/Debian:

sudo apt install zip unzip

CentOS/RHEL/Rocky:

sudo dnf install zip unzip

文本操作

vim 文本编辑器

Vim 是 Vi 的增强版,支持更多编辑能力和语法高亮,但部分精简 Linux 系统中可能只安装 Vi。

打开文件:

vim nginx.conf

Vim 最重要的是理解它存在不同的操作模式。


1. 普通模式

启动 Vim 后默认进入普通模式。

此时输入字符不会直接写入文件,而是被作为命令解释。

进入输入模式

i

也常见:

a
o

其中:

  • i:从光标当前位置前开始输入
  • a:从光标当前位置后开始输入
  • o:在下一行新建一行并输入

撤销

u

重做:

Ctrl+R

复制

复制当前行:

yy

复制 3 行:

3yy

删除 / 剪切

删除当前行:

dd

删除 3 行:

3dd

被删除的内容会进入 Vim 寄存器,因此通常也可以再通过 p 粘贴。


粘贴

p

对于整行内容通常粘贴到当前行之后。

P

粘贴到当前行之前。

这里所说的“复制内容”默认属于 Vim 自己的寄存器,并不等同于操作系统剪贴板


删除字符

x

2. 输入模式

在普通模式按:

i

进入输入模式后,就可以像普通文本编辑器一样输入文本。

按:

Esc

返回普通模式。


3. 命令行模式

普通模式输入:

:

进入命令行模式。

保存

:w

退出

:q

如果存在未保存修改则拒绝退出。

保存并退出

:wq

也可以在普通模式使用:

ZZ

放弃修改强制退出

:q!

显示行号

:set number

简写:

:set nu

关闭:

:set nonumber

或:

:set nonu

查找

向下搜索:

/word

向上搜索:

?word

继续寻找下一个:

n

反方向:

N

替换

全文替换:

:%s/word1/word2/g

全文替换并逐次确认:

:%s/word1/word2/gc

可视模式

普通模式输入:

v

进入字符选择。

选择后:

y

复制。

d

删除。

整行选择可以使用:

V

复杂指令与批处理

管道

Linux 中:

|

表示把左侧程序的标准输出传递给右侧程序。

例如:

ps aux | grep java

先执行:

ps aux

再让 grep 从结果中筛选 java

持续查看日志:

tail -f app.log | grep ERROR

表示持续读取日志,并只输出包含 ERROR 的内容。


输出重定向

覆盖写入

command > file.txt

例如:

echo hello > a.txt

注意:

>

会覆盖原文件。


追加写入

command >> file.txt

例如:

echo hello >> a.txt

错误输出

Linux 默认存在:

0    stdin   标准输入
1    stdout  标准输出
2    stderr  标准错误

因此:

command > app.log 2>&1

表示标准输出和错误输出都写到 app.log

丢弃错误:

command 2>/dev/null

&& 和 ;

连续执行:

command1 ; command2

无论第一条成功还是失败,都会继续执行第二条。

只有第一条成功才执行第二条:

command1 && command2

例如:

docker build -t app . && docker run app

其他实用操作

命令历史

查看历史命令:

history

执行上一条命令:

!!

例如:

apt update

发现权限不足,可以:

sudo !!

实际相当于:

sudo apt update

执行最近一条指定开头的命令

Bash 的交互式 Shell 中可以使用:

!scp

执行历史记录里最近一条以 scp 开头的命令。

例如之前执行:

scp -P 9922 app.jar root@1.2.3.4:/opt/app/

之后输入:

!scp

会再次执行该命令。

因为命令会立即执行,使用之前应确认历史内容,尤其不要随意对 rm 等危险命令使用历史展开。


Tab 自动补全

Shell 中输入:

cd /etc/ng

按:

Tab

通常可以自动补全:

cd /etc/nginx/

命令、文件路径等都可以使用 Tab 补全。

这是 Linux 命令行最重要的效率工具之一。


Ctrl+C

停止当前前台程序:

Ctrl+C

例如:

tail -f app.log

可以使用 Ctrl+C 退出。


Ctrl+L

清空终端显示:

Ctrl+L

与:

clear

效果类似。


基础应用运维

真正的日常服务器运维通常围绕四件事展开:

安装
配置
启动
排查

例如一个 Nginx 服务出现问题,通常需要检查:

程序有没有安装
↓
配置是否正确
↓
服务是否启动
↓
端口是否监听
↓
日志有没有报错
↓
防火墙是否放行

软件安装

不同 Linux 发行版的软件包管理器不同。

Ubuntu / Debian

更新软件索引:

sudo apt update

安装:

sudo apt install nginx

删除:

sudo apt remove nginx

搜索:

apt search nginx

RHEL / Rocky Linux / AlmaLinux / 新版 CentOS

通常使用:

sudo dnf install nginx

删除:

sudo dnf remove nginx

搜索:

dnf search nginx

部分旧版 CentOS 使用:

yum

例如:

yum install nginx

现代发行版中 dnf 已逐步取代 yum,部分系统上的 yum 实际也是兼容入口。


查看程序是否存在

which nginx

或者:

command -v nginx

查看版本:

nginx -v

systemd 服务管理

现代主流 Linux 发行版大量服务通过 systemd 管理。

例如:

nginx
docker
mysql
sshd

查看状态

systemctl status nginx

这是排查服务问题最常使用的命令之一。


启动

sudo systemctl start nginx

停止

sudo systemctl stop nginx

重启

sudo systemctl restart nginx

重新加载配置

如果服务支持:

sudo systemctl reload nginx

相比 restart,reload 通常不会完全终止服务。


开机启动

sudo systemctl enable nginx

立即启动并设置开机启动:

sudo systemctl enable --now nginx

取消开机启动:

sudo systemctl disable nginx

日志查看

发生故障后,日志通常比反复重启服务更重要

journalctl

systemd 管理的服务通常可以通过:

journalctl -u nginx

查看日志。

查看最近 100 行:

journalctl -u nginx -n 100

持续查看:

journalctl -u nginx -f

查看本次系统启动之后的日志:

journalctl -u nginx -b

/var/log

传统日志通常位于:

/var/log

例如:

/var/log/nginx/
/var/log/mysql/
/var/log/syslog
/var/log/messages

具体位置取决于发行版和应用配置。


端口与网络排查

假设服务宣称运行在:

8080

首先需要确认端口是否真的被监听。

ss

推荐使用:

ss -lntp

其中:

  • l:只显示监听状态
  • n:直接显示数字端口
  • t:TCP
  • p:显示对应进程

查询 8080:

ss -lntp | grep 8080

例如:

LISTEN 0 128 0.0.0.0:8080 ...

说明程序正在监听 8080。


测试本机服务

例如:

curl http://127.0.0.1:8080

如果本机可以访问,而外部机器无法访问,问题可能位于:

程序监听地址
防火墙
云服务器安全组
Nginx
网络

而不一定是程序自身。


IP 地址

查看服务器 IP:

ip addr

简写:

ip a

网络连通性

ping 8.8.8.8

但需要注意,部分服务器或网络会禁用 ICMP,因此 ping 不通并不能百分之百说明服务器不可访问。


防火墙

Linux 防火墙管理方式因发行版而异。

此外,如果使用:

  • 阿里云
  • 腾讯云
  • AWS
  • Azure

等云服务器,还需要同时检查云平台的:

安全组 / Firewall Rules

服务器本机开放端口,但安全组未开放时,公网仍然无法访问。


Ubuntu:ufw

查看:

sudo ufw status

开放 80:

sudo ufw allow 80/tcp

开放 443:

sudo ufw allow 443/tcp

删除规则:

sudo ufw delete allow 80/tcp

RHEL / Rocky:firewalld

查看状态:

sudo firewall-cmd --state

查看规则:

sudo firewall-cmd --list-all

开放 HTTP:

sudo firewall-cmd --permanent --add-service=http

开放 HTTPS:

sudo firewall-cmd --permanent --add-service=https

重新加载:

sudo firewall-cmd --reload

开放指定端口:

sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

Nginx 基础维护

查看状态

systemctl status nginx

检查配置

每次修改 Nginx 配置后,都应该先执行:

nginx -t

如果显示类似:

syntax is ok
test is successful

再重新加载:

systemctl reload nginx

不要修改配置后直接重启。

否则配置存在语法错误时可能导致服务启动失败。


常见配置目录

Ubuntu/Debian 常见:

/etc/nginx/nginx.conf
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/

RHEL 系发行版常见:

/etc/nginx/nginx.conf
/etc/nginx/conf.d/

但实际位置以当前服务器配置为准。


实操:Nginx HTTPS 证书更换

假设现有 Nginx 配置类似:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

证书即将过期,需要人工替换。

1. 找到实际证书位置

可以搜索:

grep -R "ssl_certificate" /etc/nginx/

找到:

ssl_certificate
ssl_certificate_key

对应路径。

不要在不知道 Nginx 实际使用哪个证书的情况下直接覆盖文件。


2. 备份旧证书

例如:

cp example.com.pem example.com.pem.bak
cp example.com.key example.com.key.bak

3. 上传新证书

假设上传:

example.com.pem
example.com.key

替换对应路径。

证书私钥应该严格限制权限,例如:

chmod 600 example.com.key

不要把私钥上传到公开仓库。


4. 检查证书与私钥路径

确认 Nginx:

ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;

路径正确。


5. 检查配置

nginx -t

只有检查通过后才继续。


6. Reload

systemctl reload nginx

一般无需 restart。


7. 验证

curl -I https://example.com

也可以:

openssl s_client -connect example.com:443 -servername example.com

查看服务器实际返回的证书。

如果使用 Let's Encrypt / Certbot,则应该优先使用自动续期机制,而不是长期人工更换证书。


常见故障排查思路

一个 Web 服务无法访问时,可以按照如下顺序排查:

1. 服务器是否正常
        ↓
2. 应用进程是否存在
        ↓
3. 应用日志是否报错
        ↓
4. 目标端口是否监听
        ↓
5. 本机 curl 是否能访问
        ↓
6. Nginx 是否正常
        ↓
7. Nginx 配置是否正确
        ↓
8. Linux 防火墙是否放行
        ↓
9. 云服务器安全组是否放行
        ↓
10. DNS 是否解析正确

常用命令:

top
free -h
df -h

systemctl status nginx

journalctl -u nginx -n 100

ps aux | grep app

ss -lntp

curl http://127.0.0.1:8080

nginx -t

curl -I https://example.com

相比“看到打不开就重启服务器”,这种逐层排查方式能够更快找到真正的问题。


进阶:容器化运维

Docker 基础概念

Docker 最容易混淆的是:

镜像 Image
容器 Container
数据卷 Volume
网络 Network

可以简单理解:

镜像 ≈ 软件安装包 / 程序模板
容器 ≈ 镜像运行之后产生的实例

例如:

docker pull nginx

下载的是:

nginx 镜像

执行:

docker run nginx

才会基于这个镜像创建并运行一个容器。

一个镜像可以创建多个容器。


镜像

查看:

docker images

例如:

REPOSITORY   TAG       IMAGE ID
nginx        latest    ...
mysql        8.4       ...

删除:

docker rmi IMAGE_ID

容器

查看正在运行的容器:

docker ps

查看全部容器,包括已经停止的:

docker ps -a

Volume

容器自身文件系统通常不应该被当成永久数据存储。

数据库、用户上传文件等重要数据通常使用:

  • Volume
  • bind mount

持久化。

例如:

docker run \
  -v /opt/mysql/data:/var/lib/mysql \
  mysql

表示:

宿主机 /opt/mysql/data
        ↓
容器 /var/lib/mysql

端口映射

例如:

docker run -p 8080:80 nginx

表示:

服务器 8080
    ↓
容器 80

因此访问:

服务器IP:8080

实际上会被转发给容器中的 80 端口。


Docker Compose

当一个应用需要多个容器,例如:

Web
MySQL
Redis

继续维护大量 docker run 命令会非常困难。

Docker Compose 允许使用一个 YAML 文件描述整个应用。

现代 Docker 环境一般使用:

docker compose

而不是旧版独立程序:

docker-compose

一个简单的:

services:
  nginx:
    image: nginx:latest
    ports:
      - "8080:80"
    restart: always

启动:

docker compose up -d

查看:

docker compose ps

查看日志:

docker compose logs

持续查看:

docker compose logs -f

停止并删除 Compose 创建的容器和网络:

docker compose down

重新拉取镜像:

docker compose pull

重新创建:

docker compose up -d

一个常见更新流程:

docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100

Docker 常用指令

查看容器

运行中的:

docker ps

全部:

docker ps -a

启动容器

docker start 容器名

或:

docker start 容器ID

停止

docker stop 容器名

docker stop 会先尝试让容器中的主进程正常退出。


重启

docker restart 容器名

删除容器

docker rm 容器名

删除运行中的容器:

docker rm -f 容器名

-f 会强制终止并删除容器,应谨慎使用。


查看日志

docker logs 容器名

查看最后 100 行:

docker logs --tail 100 容器名

持续查看:

docker logs -f 容器名

显示时间:

docker logs -t 容器名

修改重启策略

docker update --restart=always 容器名

常见策略:

no
always
unless-stopped
on-failure

在容器中执行命令

docker exec 容器名 ls /

交互式进入:

docker exec -it 容器名 bash

部分精简镜像没有 Bash,这时使用:

docker exec -it 容器名 sh

退出 docker exec 创建的 Shell,通常直接输入:

exit

即可。

Ctrl+PCtrl+Q 是 Docker 的默认 detach 按键组合,在支持相应 TTY/attach 场景时可以在不停止容器的情况下脱离连接,但日常通过 docker exec -it ... bash 进入容器时通常直接 exit 更容易理解。


拉取镜像

docker pull nginx

未指定 tag 时等价于:

docker pull nginx:latest

注意:

latest

只是一个名为 latest 的标签,并不从语义上保证它一定是该软件所有版本中“最新、最合适”的版本。

生产环境更建议明确指定版本,例如:

docker pull nginx:1.28

具体 tag 以镜像仓库实际提供的版本为准。


搜索镜像

docker search nginx

它主要用于搜索 Docker Hub 上的镜像仓库,并不是用来列出某个镜像的所有版本标签。


查看本地镜像

docker images

也可以:

docker image ls

删除镜像

docker rmi IMAGE_ID

查看容器详细信息

docker inspect 容器名

获取 Docker 网络中的容器 IP,可以使用:

docker inspect \
  -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
  容器名

但正常应用访问不应该依赖容器动态 IP。

同一 Docker 网络中的容器一般通过:

容器名 / Compose service 名

互相访问。


查看资源占用

docker stats

可以实时看到:

CPU
内存
网络
磁盘 IO

Ctrl+C 退出。


Docker 日志治理

Docker 默认情况下可能持续保存容器标准输出。

如果应用产生大量日志而没有日志轮转,有可能最终占满服务器磁盘。

首先可以检查:

docker system df

查看 Docker 整体磁盘使用情况。

查看容器日志:

docker logs --tail 100 容器名

Docker 使用 json-file 日志驱动时,其内部日志文件通常位于 Docker 数据目录,但这些文件应由 Docker Daemon 管理,不建议直接修改、删除或使用 cat /dev/null 强行截断

正确方法是配置日志轮转。


全局配置

修改:

/etc/docker/daemon.json

例如:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

其中:

max-size

表示单个日志文件最大尺寸。

max-file

表示最多保存多少个轮转文件。

修改后重启 Docker:

sudo systemctl restart docker

需要注意,全局日志配置通常只对之后新创建的容器生效,已有容器不会因为修改 Daemon 配置而自动套用新的日志设置。


docker run 指定

创建容器时:

docker run \
  --log-opt max-size=100m \
  --log-opt max-file=3 \
  nginx

Compose 指定

services:
  app:
    image: myapp:latest

    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "3"

对于生产服务器,应在部署阶段配置日志轮转,而不是等磁盘占满后再人工清理。


Docker 磁盘清理

查看 Docker 空间:

docker system df

查看未使用镜像:

docker images

删除指定镜像:

docker rmi IMAGE_ID

清理未使用资源:

docker system prune

它可能删除:

  • 已停止容器
  • 未使用网络
  • dangling 镜像
  • 构建缓存

执行前应仔细阅读 Docker 给出的确认内容。

更加激进的:

docker system prune -a

会进一步删除未被容器使用的镜像,生产服务器上不要不加判断地执行。


Docker 开发测试

构建镜像

假设当前目录存在:

Dockerfile

注意标准文件名是:

Dockerfile

而不是:

DOCKERFILE

构建:

docker build -t xx-demo:latest .

保存镜像

docker save -o xx-demo.tar xx-demo:latest

加载镜像

docker load -i xx-demo.tar

这种方式适合:

  • 离线服务器
  • 临时测试
  • 无镜像仓库环境

正式 CI/CD 流程通常会把镜像:

docker push

到镜像仓库,然后由服务器:

docker pull

部署。


启动

docker run \
  -d \
  -p 80:80 \
  -p 443:443 \
  --name xx-demo \
  xx-demo:latest

其中:

  • -d:后台运行
  • -p:端口映射
  • --name:设置容器名

常用日常运维速查

看机器资源

top
free -h
df -h

找磁盘占用

du -sh ./*
du -sh /var/*

看进程

ps aux | grep java
pgrep -af java

看监听端口

ss -lntp

测 HTTP 服务

curl http://127.0.0.1:8080

看 systemd 服务

systemctl status nginx

看 systemd 日志

journalctl -u nginx -n 100
journalctl -u nginx -f

检查 Nginx

nginx -t
systemctl reload nginx

看 Docker 容器

docker ps
docker ps -a

看 Docker 日志

docker logs --tail 100 -f app

进入 Docker 容器

docker exec -it app bash

没有 Bash:

docker exec -it app sh

最后:运维时最重要的习惯

对于刚开始接触 Linux 运维的人,比记住大量命令更重要的是养成以下习惯:

  1. 修改之前先备份

    cp nginx.conf nginx.conf.bak
    
  2. 删除之前先确认路径

    ls /准备删除的目录
    

    确认无误后再:

    rm -rf ...
    
  3. 配置修改后先检查,再重载

    例如 Nginx:

    nginx -t && systemctl reload nginx
    
  4. 出现问题先看日志,不要第一时间重启机器

    systemctl status xxx
    journalctl -u xxx
    docker logs xxx
    
  5. 先确认服务,再确认端口,再确认网络

    systemctl status xxx
    ss -lntp
    curl 127.0.0.1:端口
    
  6. 避免随意使用 777kill -9rm -rf

    这些命令不是不能用,而是不应该把它们作为解决问题的第一选择。

  7. 生产环境明确记录每一次修改

    至少应该知道:

    改了什么
    为什么改
    原配置是什么
    如何回滚
    

掌握这些基本方法后,即使没有专业 Linux 运维经验,也已经能够独立处理绝大多数开发团队中常见的服务器启停、部署、日志查看、资源排查、Nginx 维护和 Docker 日常运维工作。