feat: add comprehensive backend topics and fix build issues

## 新增内容

### 附录文档扩展
- 扩展前端项目架构文档 (frontend-project-architecture.md)
- 扩展后端项目架构文档 (backend-project-architecture.md)
- 扩展数据治理文档 (data-governance.md)
- 扩展数据可视化文档 (data-visualization.md)
- 扩展分布式系统文档 (distributed-systems.md)
- 扩展高可用文档 (high-availability.md)
- 扩展单体到微服务文档 (monolith-to-microservices.md)
- 扩展系统设计方法论文档 (system-design-methodology.md)
- 扩展 Docker 容器文档 (docker-containers.md)
- 扩展 Kubernetes 文档 (kubernetes.md)
- 扩展 Linux 基础文档 (linux-basics.md)
- 扩展神经网络文档 (neural-networks.md)

### 新增交互式组件
- 数据治理组件: DataQualityDemo, DataGovernanceFrameworkDemo, DataLineageDemo
- 数据可视化组件: ChartTypeSelectorDemo, DashboardLayoutDemo
- 分布式系统组件: CAPTheoremDemo, ConsistencyModelsDemo, DistributedChallengesDemo
- 高可用组件: AvailabilityCalculatorDemo, FailoverStrategyDemo
- 系统设计组件: SystemDesignStepsDemo, CapacityEstimationDemo
- Docker 容器组件: DockerArchitectureDemo, DockerLifecycleDemo
- Kubernetes 组件: K8sArchitectureDemo, K8sWorkloadsDemo
- Linux 基础组件: LinuxFileSystemDemo, LinuxCommandDemo, LinuxPermissionsDemo
- 神经网络组件: NeuronDemo, NetworkLayersDemo, NetworkArchitectureDemo
- 单体到微服务组件: ArchEvolutionDemo
- 项目架构组件: ProjectArchitectureComparisonDemo
- 附录导航组件: AppendixFlowMap

### 英文版重构
- 将 en-us 目录重命名为 en
- 更新相关配置和组件中的语言代码

## Bug 修复
- 修复 index.js 中重复的组件导入语句导致的 build 失败
- 恢复被注释的 InvertedIndexDemo 和 SearchRelevanceDemo 导入
- 修复 HomeFeatures.vue 中 en-us 与 config.mjs 中 en 不一致导致的语言切换问题

## 其他改进
- 添加构建脚本 (scripts/build.mjs)
- 更新依赖版本
This commit is contained in:
sanbuphy
2026-02-26 04:35:28 +08:00
parent df51f84ab5
commit ef70b1d8e1
84 changed files with 12917 additions and 3477 deletions
@@ -1,3 +1,221 @@
# Docker 容器化
> 待实现
::: tip 前言
**"在我机器上能跑"是开发者最经典的借口,Docker 让这个借口彻底消失。** 容器化技术将应用及其所有依赖打包成一个标准化的单元,确保在任何环境中都能一致运行。它是现代软件交付的基石。
:::
**这篇文章会带你学什么?**
学完这章后,你将获得:
- **核心概念**:理解镜像、容器、仓库三大核心概念
- **架构对比**:明白容器和虚拟机的本质区别
- **实操能力**:掌握 Dockerfile 编写和常用命令
- **编排基础**:学会用 Docker Compose 管理多服务应用
- **最佳实践**:了解镜像优化、安全加固等生产级实践
| 章节 | 内容 | 核心概念 |
|-----|------|---------|
| **第 1 章** | 为什么需要容器 | 环境一致性、资源效率、标准化交付 |
| **第 2 章** | 核心概念 | 镜像、容器、仓库、Dockerfile |
| **第 3 章** | Docker 生命周期 | 编写、构建、推送、运行、管理 |
| **第 4 章** | Docker Compose | 多服务编排、网络、数据卷 |
| **第 5 章** | 最佳实践 | 镜像优化、安全、多阶段构建 |
---
## 1. 为什么需要容器?
在容器出现之前,部署一个应用需要在服务器上手动安装运行时、配置环境变量、处理依赖冲突。不同环境(开发、测试、生产)之间的差异是 bug 的温床。
<DockerArchitectureDemo />
### 容器解决了什么问题?
| 问题 | 传统方式 | 容器方式 |
|------|---------|---------|
| 环境不一致 | "我本地能跑" | 打包所有依赖,到处一致 |
| 依赖冲突 | App A 要 Node 14App B 要 Node 18 | 每个容器独立环境 |
| 资源浪费 | 每个 VM 一个完整 OS | 共享内核,MB 级开销 |
| 部署慢 | 手动安装配置 | docker run 一条命令 |
| 扩容难 | 新建 VM、装环境、部署 | 秒级启动新容器 |
::: tip 容器的本质
容器不是轻量级虚拟机。它的本质是**被隔离的进程**。Linux 内核通过两个机制实现容器:
- **Namespace**:隔离进程的视野(PID、网络、文件系统等)
- **Cgroups**:限制进程的资源使用(CPU、内存、IO)
容器里的进程和宿主机上的普通进程没有本质区别,只是被"关在了一个看不到外面的房间里"。
:::
---
## 2. 核心概念
Docker 的世界围绕三个核心概念:镜像(Image)、容器(Container)、仓库(Registry)。
| 概念 | 类比 | 说明 |
|------|------|------|
| 镜像(Image) | 类 / 模板 | 只读的应用模板,包含代码、运行时、库、配置 |
| 容器(Container) | 实例 / 对象 | 镜像的运行实例,可读写,有独立的生命周期 |
| 仓库(Registry) | 应用商店 | 存储和分发镜像的服务(Docker Hub、ACR、ECR |
| Dockerfile | 配方 / 蓝图 | 定义如何构建镜像的文本文件 |
| 数据卷(Volume) | 外接硬盘 | 持久化数据,容器删除后数据不丢失 |
### 镜像的分层结构
Docker 镜像由多个只读层(Layer)叠加而成,每条 Dockerfile 指令创建一层:
```
┌─────────────────────────┐
│ CMD ["node", "app.js"] │ ← 启动命令层
├─────────────────────────┤
│ COPY . /app │ ← 应用代码层(经常变)
├─────────────────────────┤
│ RUN npm install │ ← 依赖安装层(偶尔变)
├─────────────────────────┤
│ FROM node:18-alpine │ ← 基础镜像层(很少变)
└─────────────────────────┘
```
::: tip 为什么分层很重要?
Docker 会缓存每一层。如果某一层没有变化,构建时会直接复用缓存。所以 Dockerfile 中应该把**变化频率低的指令放在前面**(如安装依赖),**变化频率高的放在后面**(如复制代码)。这样大部分构建都能命中缓存,速度快很多。
:::
---
## 3. Docker 生命周期
从编写 Dockerfile 到容器运行,Docker 的工作流程是一条清晰的流水线。
<DockerLifecycleDemo />
### Dockerfile 常用指令速查
| 指令 | 作用 | 示例 |
|------|------|------|
| `FROM` | 指定基础镜像 | `FROM node:18-alpine` |
| `WORKDIR` | 设置工作目录 | `WORKDIR /app` |
| `COPY` | 复制文件到镜像 | `COPY package.json ./` |
| `RUN` | 构建时执行命令 | `RUN npm install` |
| `ENV` | 设置环境变量 | `ENV NODE_ENV=production` |
| `EXPOSE` | 声明端口(仅文档作用) | `EXPOSE 3000` |
| `CMD` | 容器启动命令 | `CMD ["node", "app.js"]` |
| `ENTRYPOINT` | 容器入口点(不易被覆盖) | `ENTRYPOINT ["nginx"]` |
---
## 4. Docker Compose:多服务编排
真实项目通常不止一个容器。一个 Web 应用可能需要:应用服务器 + 数据库 + Redis + Nginx。Docker Compose 用一个 YAML 文件定义和管理多个容器。
### docker-compose.yml 示例
```yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
db:
image: postgres:15-alpine
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=secret
redis:
image: redis:7-alpine
volumes:
db-data:
```
### Compose 核心概念
| 概念 | 说明 | 示例 |
|------|------|------|
| services | 定义各个容器服务 | app、db、redis |
| volumes | 持久化数据卷 | db-data 保存数据库文件 |
| networks | 自定义网络(默认自动创建) | 服务间通过服务名互相访问 |
| depends_on | 启动顺序依赖 | app 依赖 db 和 redis |
| environment | 环境变量 | 数据库密码、连接地址 |
::: tip 服务发现
在 Docker Compose 中,服务名就是主机名。app 容器可以直接用 `db:5432` 访问数据库,用 `redis:6379` 访问 Redis,不需要知道 IP 地址。这是 Docker 内置 DNS 的功劳。
:::
---
## 5. 最佳实践
### 5.1 多阶段构建(Multi-stage Build
多阶段构建是优化镜像大小的利器。构建阶段安装所有工具和依赖,最终阶段只保留运行时需要的文件。
```dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 运行阶段
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]
```
### 5.2 镜像优化清单
| 优化项 | 做法 | 效果 |
|--------|------|------|
| 选择小基础镜像 | 用 `alpine` 而非 `ubuntu` | 镜像从 ~200MB 降到 ~50MB |
| 合并 RUN 指令 | 多个命令用 `&&` 连接 | 减少镜像层数 |
| 使用 .dockerignore | 排除 node_modules、.git 等 | 加速构建,减小上下文 |
| 多阶段构建 | 分离构建和运行环境 | 最终镜像不含构建工具 |
| 固定版本号 | `node:18.17-alpine` 而非 `node:latest` | 构建可重复 |
### 5.3 安全实践
| 实践 | 说明 |
|------|------|
| 不用 root 运行 | `USER node` 指定非 root 用户 |
| 扫描漏洞 | `docker scout` 或 Trivy 扫描镜像 |
| 最小权限 | 只安装必要的包,不装调试工具 |
| 不硬编码密钥 | 用环境变量或 Docker Secrets |
| 定期更新基础镜像 | 及时修复安全漏洞 |
---
## 总结
Docker 容器化是现代软件交付的基础设施,理解它对于任何开发者都至关重要。
回顾本章的关键要点:
1. **容器 vs 虚拟机**:容器共享宿主内核,更轻量、更快,但隔离性略弱于 VM
2. **核心三件套**:镜像(模板)、容器(实例)、仓库(分发)
3. **Dockerfile**:分层构建,利用缓存,变化少的指令放前面
4. **Docker Compose**:用 YAML 定义多服务应用,服务名即主机名
5. **生产实践**:多阶段构建减小镜像、alpine 基础镜像、非 root 运行
## 延伸阅读
- [Docker 官方文档](https://docs.docker.com/) - 最权威的参考资料
- [Docker Getting Started](https://docs.docker.com/get-started/) - 官方入门教程
- [Dockerfile Best Practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) - 官方最佳实践指南
- [Docker Compose 文档](https://docs.docker.com/compose/) - Compose 完整参考
@@ -1,3 +1,192 @@
# Kubernetes 编排
> 待实现
::: tip 前言
**Docker 解决了"打包"问题,Kubernetes 解决了"管理"问题。** 当你有几十上百个容器需要部署、扩缩容、故障恢复时,手动管理是不现实的。Kubernetes(K8s)就是容器的"操作系统",它自动化了容器化应用的部署、扩展和运维。
:::
**这篇文章会带你学什么?**
学完这章后,你将获得:
- **架构理解**:掌握 K8s 控制平面和工作节点的组成
- **核心资源**:熟悉 Pod、Deployment、Service 等核心概念
- **声明式管理**:理解"声明期望状态,系统自动收敛"的思想
- **运维能力**:了解滚动更新、自动扩缩容、健康检查等机制
- **实战入门**:能用 kubectl 和 YAML 部署一个完整应用
| 章节 | 内容 | 核心概念 |
|-----|------|---------|
| **第 1 章** | 为什么需要 K8s | 容器编排的挑战 |
| **第 2 章** | K8s 架构 | 控制平面、工作节点、etcd |
| **第 3 章** | 核心资源 | Pod、Deployment、Service、Ingress |
| **第 4 章** | 声明式管理 | YAML、kubectl、控制循环 |
| **第 5 章** | 运维实践 | 滚动更新、HPA、健康检查 |
---
## 1. 为什么需要 Kubernetes
Docker 让单个容器的打包和运行变得简单,但当你面对以下场景时,手动管理就力不从心了:
| 挑战 | 描述 | K8s 的解决方案 |
|------|------|---------------|
| 多实例部署 | 一个服务需要运行 10 个副本 | Deployment 自动管理副本数 |
| 故障恢复 | 某个容器挂了需要自动重启 | 控制器自动检测并重建 Pod |
| 服务发现 | 容器 IP 会变,怎么找到对方? | Service 提供稳定的 DNS 和 IP |
| 滚动更新 | 更新版本时不能停服 | 逐步替换旧 Pod,零停机 |
| 弹性伸缩 | 流量高峰自动扩容 | HPA 根据 CPU/内存自动调整副本数 |
| 资源调度 | 把容器放到最合适的机器上 | Scheduler 智能调度 |
::: tip K8s 的核心思想:声明式
你不需要告诉 K8s "启动 3 个容器"(命令式),而是告诉它 "我要 3 个副本在运行"(声明式)。K8s 会持续监控,确保实际状态与你声明的期望状态一致。如果一个 Pod 挂了,它会自动创建新的来补上。
:::
---
## 2. Kubernetes 架构
K8s 集群由控制平面(Control Plane)和工作节点(Worker Node)组成。
<K8sArchitectureDemo />
### 一次请求的完整路径
```
用户请求 → Ingress Controller → Service → kube-proxy → Pod(容器)
Endpoint 列表(由 Service 维护)
```
---
## 3. 核心资源对象
K8s 通过各种"资源对象"来描述集群的期望状态。
<K8sWorkloadsDemo />
### 资源对象分类
| 类别 | 资源 | 用途 |
|------|------|------|
| 工作负载 | Pod、Deployment、StatefulSet、DaemonSet、Job | 运行应用 |
| 网络 | Service、Ingress、NetworkPolicy | 服务发现和流量管理 |
| 配置 | ConfigMap、Secret | 配置和敏感数据管理 |
| 存储 | PersistentVolume、PersistentVolumeClaim | 持久化存储 |
| 调度 | Node、Namespace、ResourceQuota | 资源隔离和限制 |
---
## 4. 声明式管理与 kubectl
### 控制循环(Reconciliation Loop
K8s 的核心工作机制是控制循环:
```
观察(Observe)→ 比较(Diff)→ 行动(Act)→ 观察...
↓ ↓ ↓
读取实际状态 与期望状态对比 执行修正操作
```
你声明 `replicas: 3`,控制器发现只有 2 个 Pod 在运行,就会创建 1 个新的。这个循环每隔几秒执行一次,确保系统始终向期望状态收敛。
### kubectl 常用命令
| 命令 | 作用 | 示例 |
|------|------|------|
| `kubectl apply -f` | 应用 YAML 配置 | `kubectl apply -f deployment.yaml` |
| `kubectl get` | 查看资源列表 | `kubectl get pods -o wide` |
| `kubectl describe` | 查看资源详情 | `kubectl describe pod my-app-xxx` |
| `kubectl logs` | 查看 Pod 日志 | `kubectl logs -f my-app-xxx` |
| `kubectl exec` | 进入 Pod 终端 | `kubectl exec -it my-app-xxx -- sh` |
| `kubectl delete` | 删除资源 | `kubectl delete -f deployment.yaml` |
| `kubectl scale` | 手动扩缩容 | `kubectl scale deploy my-app --replicas=5` |
::: tip apply vs create
`kubectl create` 是命令式的——"创建这个资源",如果已存在会报错。`kubectl apply` 是声明式的——"确保资源是这个状态",不存在就创建,已存在就更新。生产环境中应该始终使用 `apply`
:::
---
## 5. 运维实践
### 5.1 滚动更新与回滚
Deployment 默认使用滚动更新策略:逐步创建新版本 Pod,同时逐步终止旧版本 Pod。
```yaml
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多多创建 1 个 Pod
maxUnavailable: 0 # 不允许有 Pod 不可用
```
| 操作 | 命令 |
|------|------|
| 更新镜像 | `kubectl set image deploy/my-app app=my-app:2.0` |
| 查看更新状态 | `kubectl rollout status deploy/my-app` |
| 查看历史版本 | `kubectl rollout history deploy/my-app` |
| 回滚到上一版本 | `kubectl rollout undo deploy/my-app` |
### 5.2 自动扩缩容(HPA
HPAHorizontal Pod Autoscaler)根据 CPU、内存或自定义指标自动调整 Pod 副本数。
```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
```
### 5.3 健康检查(Probe
K8s 通过三种探针监控 Pod 的健康状态:
| 探针 | 作用 | 失败后果 |
|------|------|---------|
| livenessProbe | 检测容器是否存活 | 重启容器 |
| readinessProbe | 检测容器是否就绪 | 从 Service 摘除,不接收流量 |
| startupProbe | 检测容器是否启动完成 | 启动期间不执行其他探针 |
::: tip 探针的重要性
没有配置健康检查的 Pod,K8s 只能通过进程是否存在来判断健康状态。但很多时候进程还在,服务已经不响应了(比如死锁、OOM 边缘)。配置 livenessProbe 可以让 K8s 自动重启这些"假死"的容器。
:::
---
## 总结
Kubernetes 是容器编排的事实标准,理解它的核心概念是云原生开发的基础。
回顾本章的关键要点:
1. **声明式管理**:告诉 K8s "我要什么",而不是"怎么做",控制循环自动收敛
2. **架构分层**:控制平面负责决策,工作节点负责执行,etcd 存储状态
3. **核心资源**Pod(最小单元)、Deployment(副本管理)、Service(服务发现)、Ingress(外部入口)
4. **运维自动化**:滚动更新零停机、HPA 弹性伸缩、探针自动故障恢复
5. **配置分离**ConfigMap 和 Secret 让配置与镜像解耦
## 延伸阅读
- [Kubernetes 官方文档](https://kubernetes.io/zh-cn/docs/) - 最权威的中文参考
- [Kubernetes the Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way) - 从零手动搭建 K8s 集群
- [The Illustrated Children's Guide to Kubernetes](https://www.cncf.io/phippy/) - CNCF 出品的趣味入门
- [Kubernetes Patterns](https://www.oreilly.com/library/view/kubernetes-patterns-2nd/9781098131678/) - K8s 设计模式
@@ -1,3 +1,397 @@
# Linux 基础
> 待实现
::: tip 前言
**服务器的世界,Linux 是绝对的主角。** 全球超过 90% 的服务器运行 Linux,从你每天用的微信到 Google 搜索,背后都是 Linux 在支撑。作为开发者,掌握 Linux 基础不是可选项,而是必修课。
:::
**这篇文章会带你学什么?**
学完这章后,你将获得:
- **文件系统**:理解 Linux 目录结构和"一切皆文件"的哲学
- **常用命令**:掌握文件操作、文本处理、进程管理等核心命令
- **权限模型**:理解用户、组、权限的概念
- **Shell 基础**:了解管道、重定向、环境变量等 Shell 核心概念
- **实战技能**:学会日志查看、进程排查、网络诊断等运维基本功
| 章节 | 内容 | 核心概念 |
|-----|------|---------|
| **第 1 章** | 文件系统 | 目录结构、一切皆文件 |
| **第 2 章** | 常用命令 | 文件、文本、进程、网络 |
| **第 3 章** | 权限模型 | 用户、组、rwx、sudo |
| **第 4 章** | Shell 基础 | 管道、重定向、变量、脚本 |
| **第 5 章** | 实战场景 | 日志排查、性能诊断 |
---
## 1. 文件系统:一切皆文件
Linux 最核心的哲学之一就是**一切皆文件**。普通文件是文件,目录是文件,硬盘是文件,甚至网络连接、进程信息都是文件。这个统一的抽象让你可以用同一套工具(读、写、权限控制)操作几乎所有系统资源。
<LinuxFileSystemDemo />
### 目录结构速记
把 Linux 文件系统想象成一棵倒过来的树:
```
/ ← 根目录(树根)
├── home/ ← 用户的家(你的文件都在这)
├── etc/ ← 配置文件(系统的"设置面板")
├── var/ ← 变化的数据(日志、缓存)
├── usr/ ← 用户安装的程序
├── tmp/ ← 临时文件(重启就没了)
├── proc/ ← 进程信息(虚拟的,不占磁盘)
├── dev/ ← 设备文件(硬盘、终端)
├── bin/ ← 基础命令(ls、cp、mv)
├── sbin/ ← 系统管理命令(需要 root)
├── opt/ ← 第三方软件
└── root/ ← root 用户的家目录
```
### 路径的两种写法
| 类型 | 格式 | 示例 | 说明 |
|------|------|------|------|
| 绝对路径 | 从 `/` 开始 | `/home/alice/code/app.js` | 从根目录出发,不会歧义 |
| 相对路径 | 从当前目录开始 | `./code/app.js``../config` | `.` 是当前目录,`..` 是上级目录 |
::: tip "一切皆文件"的威力
想知道 CPU 信息?读文件:`cat /proc/cpuinfo`
想知道内存使用?读文件:`cat /proc/meminfo`
想产生随机数?读文件:`cat /dev/urandom`
想丢弃输出?写文件:`echo "no thanks" > /dev/null`
不需要专门的 API,读写文件就够了。这就是 Unix 哲学的优雅之处。
:::
---
## 2. 常用命令
Linux 命令遵循一个统一的格式:`命令 [选项] [参数]`。比如 `ls -la /home` 中,`ls` 是命令,`-la` 是选项,`/home` 是参数。
<LinuxCommandDemo />
### 最常用的 10 个命令
如果只能记住 10 个命令,记这些:
| 命令 | 用途 | 记忆技巧 |
|------|------|----------|
| `ls` | 列出文件 | list |
| `cd` | 切换目录 | change directory |
| `cat` | 查看文件 | concatenate |
| `grep` | 搜索文本 | global regular expression print |
| `find` | 查找文件 | 就是 find |
| `ps` | 查看进程 | process status |
| `tail -f` | 实时看日志 | 看文件"尾巴"-f 是 follow |
| `chmod` | 改权限 | change mode |
| `curl` | 发 HTTP 请求 | client URL |
| `ssh` | 远程登录 | secure shell |
### 命令组合的艺术
Linux 的强大不在于单个命令,而在于**命令组合**。通过管道 `|` 把多个简单命令串起来,解决复杂问题:
```bash
# 找出占用 CPU 最多的 5 个进程
ps aux --sort=-%cpu | head -6
# 统计日志中出现最多的错误类型
grep "ERROR" app.log | awk '{print $4}' | sort | uniq -c | sort -rn | head -10
# 查找大于 100MB 的文件
find / -size +100M -type f 2>/dev/null
# 实时监控日志中的错误
tail -f /var/log/app.log | grep --color "ERROR"
```
::: tip Unix 哲学
"做一件事,做好它。" 每个命令只负责一个功能,通过管道组合实现复杂操作。这就是为什么 Linux 命令都很短小——它们是积木,不是瑞士军刀。
:::
---
## 3. 权限模型
Linux 是多用户系统,权限模型是安全的基石。每个文件都有三组权限,分别控制**所有者(Owner)**、**所属组(Group**、**其他人(Others**能做什么。
### 读懂 `ls -l` 的输出
```bash
$ ls -l app.js
-rwxr-xr-- 1 alice developers 2048 Jan 15 10:30 app.js
│├──┤├──┤├──┤ │ │ │
│ │ │ │ │ │ └── 文件大小
│ │ │ │ │ └── 所属组
│ │ │ │ └── 所有者
│ │ │ └── 其他人权限:r-- (只读)
│ │ └── 组权限:r-x (读+执行)
│ └── 所有者权限:rwx (读+写+执行)
└── 文件类型:- 普通文件,d 目录,l 链接
```
### 权限的三种操作
| 权限 | 字母 | 数字 | 对文件的含义 | 对目录的含义 |
|------|------|------|-------------|-------------|
| 读 | `r` | 4 | 查看文件内容 | 列出目录内容(ls) |
| 写 | `w` | 2 | 修改文件内容 | 创建/删除目录中的文件 |
| 执行 | `x` | 1 | 运行程序/脚本 | 进入目录(cd) |
<LinuxPermissionsDemo />
### 数字权限速算
三个数字分别代表 Owner、Group、Others 的权限,每个数字是 r(4) + w(2) + x(1) 的和:
```
chmod 755 script.sh
7 = rwx (4+2+1) → 所有者:读+写+执行
5 = r-x (4+0+1) → 组:读+执行
5 = r-x (4+0+1) → 其他人:读+执行
```
| 常见权限 | 含义 | 典型用途 |
|---------|------|---------|
| `644` | rw-r--r-- | 普通文件(所有者可写,其他人只读) |
| `755` | rwxr-xr-x | 可执行文件/目录 |
| `600` | rw------- | 私密文件(如 SSH 密钥) |
| `777` | rwxrwxrwx | 所有人可读写执行(危险,避免使用) |
### sudo:临时获取超级权限
普通用户权限有限,有些操作需要 root 权限。`sudo` 让你临时以 root 身份执行命令:
```bash
# 普通用户无法修改系统配置
$ vim /etc/nginx/nginx.conf
# Permission denied
# 用 sudo 临时提权
$ sudo vim /etc/nginx/nginx.conf
# 输入你的密码后可以编辑
# 切换到 root 用户(谨慎使用)
$ sudo su -
```
::: warning 最小权限原则
永远不要用 `chmod 777` 解决权限问题,这等于把门锁拆了。正确做法是搞清楚谁需要什么权限,精确授予。同样,不要长期以 root 身份操作,只在必要时用 `sudo`
:::
---
## 4. Shell 基础
Shell 是你和 Linux 内核之间的"翻译官"。你输入命令,Shell 解释并交给内核执行。最常用的 Shell 是 **Bash**(大多数 Linux 发行版默认)和 **Zsh**macOS 默认)。
### 管道与重定向
这是 Shell 最强大的两个特性:
| 符号 | 名称 | 作用 | 示例 |
|------|------|------|------|
| `|` | 管道 | 把前一个命令的输出作为后一个的输入 | `cat log | grep ERROR` |
| `>` | 输出重定向 | 把输出写入文件(覆盖) | `echo "hello" > file.txt` |
| `>>` | 追加重定向 | 把输出追加到文件末尾 | `echo "world" >> file.txt` |
| `<` | 输入重定向 | 从文件读取输入 | `wc -l < file.txt` |
| `2>` | 错误重定向 | 把错误信息写入文件 | `cmd 2> error.log` |
| `2>&1` | 合并输出 | 把错误和正常输出合并 | `cmd > all.log 2>&1` |
### 环境变量
环境变量是 Shell 中的"全局配置",影响命令的行为:
```bash
# 查看所有环境变量
env
# 查看某个变量
echo $PATH
echo $HOME
# 临时设置(只在当前 Shell 有效)
export API_KEY="abc123"
# 永久设置(写入配置文件)
echo 'export API_KEY="abc123"' >> ~/.bashrc
source ~/.bashrc # 让配置立即生效
```
| 常见变量 | 含义 | 示例值 |
|---------|------|--------|
| `$PATH` | 命令搜索路径 | `/usr/local/bin:/usr/bin:/bin` |
| `$HOME` | 用户主目录 | `/home/alice` |
| `$USER` | 当前用户名 | `alice` |
| `$PWD` | 当前工作目录 | `/var/log` |
| `$SHELL` | 当前使用的 Shell | `/bin/bash` |
### Shell 脚本入门
把多个命令写进一个文件,就是 Shell 脚本。它是自动化运维的起点:
```bash
#!/bin/bash
# deploy.sh - 简单的部署脚本
APP_DIR="/opt/myapp"
LOG_FILE="/var/log/deploy.log"
echo "$(date) - 开始部署..." >> $LOG_FILE
# 拉取最新代码
cd $APP_DIR && git pull origin main
# 安装依赖
npm install --production
# 重启服务
pm2 restart myapp
echo "$(date) - 部署完成" >> $LOG_FILE
```
```bash
# 给脚本执行权限并运行
chmod +x deploy.sh
./deploy.sh
```
::: tip 脚本调试技巧
在脚本开头加 `set -ex``-e` 让脚本遇到错误立即退出(而不是继续执行),`-x` 会打印每条执行的命令(方便排查问题)。这两个选项在生产脚本中几乎是标配。
:::
---
## 5. 实战场景
理论学完了,来看几个开发中最常遇到的实战场景。
### 5.1 日志排查
服务出问题,第一反应就是看日志。以下是日志排查的常用套路:
```bash
# 1. 实时跟踪日志(最常用)
tail -f /var/log/app/error.log
# 2. 搜索特定时间段的错误
grep "2024-01-15 14:" error.log | grep "ERROR"
# 3. 统计每小时的错误数量
grep "ERROR" app.log | awk '{print substr($1,1,13)}' | uniq -c
# 4. 查看最近 100 行日志
tail -100 app.log
# 5. 在多个日志文件中搜索
grep -r "OutOfMemory" /var/log/app/
```
### 5.2 进程排查
应用卡死、CPU 飙高、内存泄漏——这些问题都需要从进程入手:
```bash
# 查看 CPU 占用最高的进程
ps aux --sort=-%cpu | head -10
# 查看内存占用最高的进程
ps aux --sort=-%mem | head -10
# 查找特定进程
ps aux | grep "node"
# 查看进程的详细信息(包括线程)
top -Hp <PID>
# 查看进程打开的文件
lsof -p <PID>
# 优雅终止进程(SIGTERM
kill <PID>
# 强制终止(SIGKILL,最后手段)
kill -9 <PID>
```
### 5.3 网络诊断
服务连不上?先搞清楚是网络问题还是应用问题:
```bash
# 测试目标是否可达
ping -c 4 google.com
# 检查端口是否开放
telnet db-server 3306
# 或者用 nc
nc -zv db-server 3306
# 查看本机监听的端口
ss -tlnp
# 或
netstat -tlnp
# DNS 解析检查
dig api.example.com
nslookup api.example.com
# 测试 HTTP 接口
curl -v http://localhost:3000/health
# 查看网络连接状态统计
ss -s
```
### 5.4 磁盘空间排查
磁盘满了是线上最常见的故障之一:
```bash
# 查看各分区使用情况
df -h
# 找出占用空间最大的目录
du -sh /* 2>/dev/null | sort -rh | head -10
# 进一步定位大目录
du -sh /var/log/* | sort -rh | head -10
# 查找大文件(>100MB
find / -type f -size +100M 2>/dev/null | head -20
# 清理常见的空间占用
# 清理旧日志
sudo journalctl --vacuum-size=500M
# 清理 Docker 无用镜像
docker system prune -a
```
::: tip 线上排查口诀
**"一看日志,二看进程,三看网络,四看磁盘"**。90% 的线上问题都能通过这四步定位到原因。养成习惯后,排查效率会大幅提升。
:::
---
## 总结
Linux 是开发者的必备技能,掌握基础就能应对大部分日常开发和运维场景。
回顾本章的关键要点:
1. **一切皆文件**:Linux 用文件抽象统一了对硬件、进程、网络等资源的访问方式
2. **命令组合**:单个命令功能简单,通过管道 `|` 组合才能发挥真正威力
3. **权限模型**Owner/Group/Others × Read/Write/Execute,用数字(如 755)快速设置
4. **Shell 基础**:管道、重定向、环境变量、脚本是自动化的基石
5. **实战排查**:日志 → 进程 → 网络 → 磁盘,四步定位大部分线上问题
## 延伸阅读
- [Linux 命令大全](https://man7.org/linux/man-pages/) - Linux man pages 官方文档
- [The Linux Command Line](https://linuxcommand.org/tlcl.php) - 免费的 Linux 命令行入门书
- [Linux Journey](https://linuxjourney.com/) - 交互式 Linux 学习网站
- [explainshell.com](https://explainshell.com/) - 输入命令自动解释每个参数的含义