跳转到主要内容

1 - 使用 ExifTool 整理个人照片

储存了十余年的个人照片,多年来反复在多个移动硬盘、网盘、NAS、手机、电脑等设备中来回迁移,早已乱的一塌糊涂。近期想对齐进行全面整理,梳理为按时间线的结构。然而很多照片的拍摄日期早已丢失,使用 ExifTool 对它们进行修复。

本文的主要记录在整理个人照片的过程中,所使用的各种命令。全部都是由 AI 提供,并经我本人验证可用的命令。

强烈建议使用前建立测试目录并复制进少许照片进行测试。

检查是否有拍摄日期

# 递归扫描当前目录下所有文件,以制表符分隔格式输出每个文件的所在目录、文件名和原始拍摄时间。
exiftool -r -T -Directory -FileName -DateTimeOriginal .

更名为拍摄日期时间戳

# 递归扫描当前目录,将含有拍摄时间的照片/视频文件重命名为拍摄时间格式(如 20231215_143022.jpg),文件名重复时自动添加数字后缀。
exiftool -r -if '$DateTimeOriginal' -d '%Y%m%d_%H%M%S' '-FileName<${DateTimeOriginal}%-c.%e' .

2 - VSCode 配置机制完整笔记

一、.vscode 目录概述

.vscode 是 VS Code 的项目级配置目录,定义"当 VS Code 打开这个项目时,该如何表现"。

常见文件结构

.vscode/
├── settings.json      # 工作区设置(覆盖用户全局设置)
├── extensions.json    # 推荐安装的扩展列表
├── launch.json        # 调试配置
├── tasks.json         # 自定义任务
└── snippets/          # 代码片段目录

二、配置层级与覆盖机制

三层架构(优先级由低到高)

VS Code 默认设置
用户级设置(~/settings.json)
工作区设置(.vscode/settings.json)← 项目级,优先级最高

关键区别

文件机制行为
settings.json增量覆盖只写3项 → 继承用户级其余7项
extensions.json全量清单只写a,b,c → 只推荐a,b,c,不继承其他
launch.json全量配置只显示配置的调试方案
tasks.json全量配置只显示定义的任务
snippets/*.json全量配置只提供定义的代码片段

示例对比

settings.json(增量)

// 用户级:a=1, b=2, c=3, d=4, e=5
// 项目级写:{"b": 20}
// 结果:a=1, b=20, c=3, d=4, e=5(继承+覆盖)

extensions.json(全量)

// 用户级:安装了 a,b,c,d
// 项目级写:{"recommendations": ["a","b"]}
// 结果:只推荐 a,b(不会推荐 c,d)

三、配置存储位置

用户级配置

类型路径(macOS/Linux)路径(Windows)
设置文件~/.config/Code/User/settings.json%APPDATA%\Code\User\settings.json
扩展目录~/.vscode/extensions/%USERPROFILE%\.vscode\extensions\
快捷键~/.config/Code/User/keybindings.json同左
代码片段~/.config/Code/User/snippets/同左

项目级配置

  • 位置:.vscode/ 目录下
  • 作用范围:仅当前项目
  • 版本控制:应提交到 Git,确保团队一致

四、扩展管理

用户级 vs 项目级

级别存储位置特点
用户级扩展~/.vscode/extensions/所有项目共享,物理安装在此
项目级推荐.vscode/extensions.json仅提示安装,不自动部署
真正隔离Dev Container容器内独立安装扩展

扩展推荐配置

{
  "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
  "unwantedRecommendations": ["some.extension.to.disable"]
}

多项目扩展隔离方案

场景:项目A用a,b,c,项目B用d,e,f,其他项目用a,b,c,d

方案实现方式适用场景
简单推荐extensions.json 分别配置只是提示,不强制
禁用配置settings.json 中禁用对方扩展扩展有冲突时
彻底隔离--user-data-dir 启动独立实例需要完全隔离

五、跨平台路径处理

核心原则

能用相对不用绝对,能用变量不用字符串

内置变量

变量含义跨平台效果
${workspaceFolder}项目根目录自动适配 Windows/macOS/Linux 路径格式
${userHome}用户主目录Windows: C:\Users\123, macOS: /Users/123
${workspaceFolderBasename}项目文件夹名project
${env:NAME}环境变量${env:HOME}

正确 vs 错误示例

// ❌ 错误:硬编码绝对路径
"python.defaultInterpreterPath": "C:/Users/123/project/venv/bin/python"

// ✅ 正确:使用变量
"python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python"
"python.analysis.extraPaths": ["${userHome}/.local/lib/python"]

特殊情况处理

如果路径完全无关(如 Windows D:\project1\123 vs macOS Documents/project1/123):

方案做法
推荐把系统特定路径放用户级 settings.json,项目级保持通用
备选使用环境变量 ${env:PROJECT1_PATH}
避免硬编码不同系统的绝对路径到项目配置

六、VS Code 设置同步

同步内容

  • ✅ 用户级 settings.json
  • ✅ 扩展列表(自动重新安装)
  • ✅ 键盘快捷键
  • ✅ 用户级代码片段
  • ✅ UI 状态

不同步内容

  • ❌ 项目级 .vscode/ 目录(需 Git 管理)
  • ❌ 扩展的本地数据/缓存

分工明确

机制用途
设置同步个人习惯跟着账号走(跨设备)
.vscode + Git团队规范跟着代码走(跨成员)

七、最佳实践总结

1. 配置原则

  • 项目级.vscode/):放团队共享、通用、跨平台的配置
  • 用户级~/settings.json):放个人偏好、系统特定的配置

2. 路径原则

  • 优先使用 ${workspaceFolder}(项目内)
  • 其次使用 ${userHome}(用户目录)
  • 避免硬编码盘符(如 D:\/Volumes/

3. 扩展原则

  • 项目必需的扩展 → extensions.json 推荐
  • 个人辅助扩展 → 用户级安装,不同步到项目

4. 调试/任务原则

  • 通用任务 → .vscode/tasks.json(全量定义)
  • 个人调试习惯 → 用户级 launch.json

八、快速参考命令

操作命令面板(Ctrl+Shift+P)
打开用户级设置(UI)Preferences: Open User Settings
打开用户级设置(JSON)Preferences: Open User Settings (JSON)
打开工作区设置(JSON)Preferences: Open Workspace Settings (JSON)
打开扩展目录Extensions: Open Extensions Folder
打开键盘快捷键Preferences: Open Keyboard Shortcuts (JSON)

3 - Docker 学习笔记

说明

Docker 核心概念

容器化技术

  • Docker 是目前最成熟高效的软件部署技术
  • Docker 就是用容器化技术给应用程序封装独立的运行环境
  • 每个运行环境就是一个==容器==
  • 运行容器的计算机被称为==宿主机==

容器与虚拟机的需求

  • 容器:多个容器共用同一个系统内核
  • 虚拟机:每个虚拟机都包含操作系统的完整内核
  • 优势:Docker 容器比虚拟机更轻、更小,启动速度更快

镜像与容器的关系

  • 镜像:镜像是容器的模板,可类比为软件安装包
  • 容器:由“软件安装包”安装出来的软件
  • 类比:
    • 类比于用模具做糕点,镜像是模具,容器是做出来的糕点
    • 可以使用一个模具(镜像)做出很多个糕点(容器)
    • 也可以将模具(镜像)分享给其他人使用

Docker 仓库

  • Docker 仓库是用来存放和分享镜像的地方
  • 用户可以将镜像上传到仓库后,供其他人下载
  • Docker Hub 是 Docker 的官方仓库,可以搜索大量镜像

Docker 安装方式

暂略~ 我日常使用 ==1Panel==、==cnb.cool==、==群晖 Nas== 这些方式管理 Docker 容器 他们都已经配置好了 Docker 环境 暂时不需要去了解 Docker 的安装

Docker 镜像管理

镜像地址

一个完整的镜像地址包含以下四部分:

docker.io/library/nginx:latest
<仓库地址>/<命名空间>/<镜像名称>:<版本标签>
  • docker.io 是 Docker Hub 官方仓库的地址,可以省略
  • library 是 Docker Hub 官方仓库的命名空间,可以省略
  • nginx 是镜像名称
  • latest 是版本标签,latest表示最新版本,可以省略
  • 示例:
    • 从官方仓库下载最新版 nginx 镜像: docker pull nginx
    • 从官方仓库的 n8n 命名空间下载镜像: docker pull n8nio/n8n
    • 从 n8n 私有仓库下载镜像: docker pull docker.n8n.io/n8nio/n8n

官方仓库的镜像往往无法直接下载,需要寻找相应的镜像站或使用代理。

//TODO

4 - Markdown 语法速查

涵盖标题、文本、列表、链接、表格、代码等常用 Markdown 语法,一份速查表快速上手。

语法速查表

功能Markdown 语法效果预览
一级标题# 标题内容最大的标题
二级标题## 标题内容
三级标题### 标题内容(依此类推,可到六级)
加粗**需要加粗的文字**需要加粗的文字
斜体*需要倾斜的文字*需要倾斜的文字
加粗并斜体***又粗又斜的文字***又粗又斜的文字
删除线~~被删除的文字~~被删除的文字
无序列表- 列表项* 列表项• 列表项
有序列表1. 列表项一
2. 列表项二
1. 列表项一
2. 列表项二
任务列表- [ ] 未完成
- [x] 已完成
☐ 未完成
☑ 已完成
引用> 这是一段引用的文字> 这是一段引用的文字
行内代码`code`用于突出显示变量或命令
代码块```python
print("Hello")
```
用于显示多行代码
链接[显示的文字](https://example.com)显示的文字
图片![替代文本](图片路径)直接显示图片
水平分割线---***一条横跨页面的线

标题

注意:所有符号都是英文输入法下的符号。井号加空格,几个井号就是几级标题,一级标题字体最大。

# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题

文本

**加粗**
*斜体*
***粗斜体***
~~删除线~~

列表

无序列表: 减号/加号/星号 + 空格,三个符号均可,建议用减号。

- 列表项 1
- 列表项 2
 - 嵌套列表项
- 列表项 3

有序列表: 数字 + 点 + 空格。

1. 列表项 a
2. 列表项 b
 1. 嵌套项 b1
3. 列表项 c

任务列表: 方括号内空格代表未完成,x 代表已完成。

- [ ] 未完成的任务
- [x] 已完成的任务

引用

> 这是一段引用
>> 嵌套引用

链接

[显示的文字](https://example.com)

直接链接:<https://github.com>

锚点链接:[链接文字][锚点名]
[锚点名]: https://example.com

图片

![替代文本](图片路径 "可选的标题")

带链接的图片:[![替代文本](图片路径)](https://example.com)

表格

竖线分隔单元格,分隔行至少三个减号,冒号控制对齐。

| 左对齐 | 居中对齐 | 右对齐 |
| :----- | :------: | -----: |
| AAA    |   BBB    |    CCC |

代码

行内代码:用反引号包裹,如 `code`

代码块:用三个反引号包裹,可指定语言。

```python
import numpy as np
def calc(a):
    return np.sqrt(a) * 3
```

脚注

要添加脚注[^01]

[^01]: 脚注内容

分割线

三个或以上的减号、星号、下划线均可。

---
***
___

注意事项

  • 所有符号都是英文输入法下的符号
  • 井号 # 后要加空格才是标题

5 - SSH 密钥配置指南

SSH 密钥的生成、绑定、配置与常用操作,从入门到进阶。

简介

SSH 密钥(SSH Key)是一种用于安全登录远程服务器的"钥匙",它由一对公钥私钥组成。与密码相比,SSH 密钥更安全,也更方便。

  • 公钥(Public Key):放在远程服务器上,可以公开。
  • 私钥(Private Key):保存在本地电脑,必须保密,不能泄露。

可以将其类比为钥匙(私钥)和锁芯(公钥),公钥放在远程服务器上,私钥保存在本地电脑里,相互配对才能正确打开。

生成密钥

在终端内执行:

  • 使用 ed25519 算法(推荐):ssh-keygen -t ed25519 -C "备注"
  • 使用 rsa 算法(兼容性好):ssh-keygen -t rsa -b 4096 -C "备注"

执行后,会让你确认密钥保存在哪里,是否需要再加一个密码。在一路回车的默认情况下,会在 ~/.ssh 目录下生成两个文件:

  • id_ed25519id_rsa 即私钥
  • id_ed25519.pubid_rsa.pub 即公钥

然后将公钥与远程服务器绑定即可。

绑定公钥

进阶:使用 ~/.ssh/config

服务器多起来后,每次 SSH 都要记 IP 和端口很麻烦。可以在 ~/.ssh/config 中为常用服务器设置别名:

# 个人服务器
Host my-server
    HostName 123.123.123.123
    User root

# Web 服务器
Host web-server
    HostName 456.456.456.456
    User admin
    Port 2222

配置后直接 ssh my-server 即可登录,不用再记 IP 和端口。

6 - MacOS 系统降级流程

本文介绍如何将 Intel 芯片的 MacOS 从 13.x 版本降级到 10.15 或 12.x 版本(已实测),其他版本仅供参考。

重要提示

降级过程会格式化全部磁盘内容,请务必提前备份所有重要数据,并在多处进行备份!

参考链接

MacOS 版本推荐

以下版本信息针对 2017 MacBook Pro 设备:

  • Ventura 13——最后一个支持的版本
  • Monterey 12——稳定性一般,兼容性较好
  • Catalina 10.15——稳定性最佳,兼容性一般

操作步骤

1. 准备工作

  1. 备份所有重要数据
  2. 退出系统的 Apple ID
  3. 准备一个 14GB 以上的 USB 闪存盘

2. 下载 MacOS

  1. 本页面 通过 App Store 下载所需的系统版本(如 Monterey 12
  2. 下载完毕后,若自动打开安装程序,直接关闭退出
  3. 确保应用程序文件夹内有名为 安装macOS Monterey 的安装器

3. 创建 macOS 安装器

  1. 插入准备的 USB 闪存盘
  2. 使用系统自带的 磁盘工具 应用,将其全盘抹掉并格式化:
    • 名称:MyVolume(建议使用此名称,方便后续操作)
    • 格式:Mac OS拓展(日志式)(是否区分大小写不影响)
  3. 启动终端,根据所需的系统版本输入命令(命令来源):
    • Catalina:sudo /Applications/Install\ macOS\ Catalina.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
    • Monterey:sudo /Applications/Install\ macOS\ Monterey.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
  4. 根据终端提示完成安装:
    • 输入登录密码(输入时终端无字符提示)
    • 输入 Y 确认全部抹掉 USB 闪存盘(弹出允许终端访问可移动宗卷的提示时点击允许)
    • 耐心等待,过程较为漫长
  5. 安装完成后,USB 闪存盘名称将改为类似 Install macOS Monterey 的名称

4. 启动 MacOS 安装程序

  1. 重启设备后,立刻按住 Option 键,直到出现可引导安装器的宗卷(即 Install macOS Monterey
  2. 通过方向键选择安装器(若无法启动,需确保“启动安全性实用工具”已设为允许从外部或可移动介质启动)

5. 安装 MacOS

  1. 进入安装器后,启动磁盘工具,抹掉内置的整个硬盘(通常被命名为 Macintosh HD):
    • 名称:Macintosh HD
    • 格式:APFS
  2. 关闭磁盘工具,返回选择 安装macOS Monterey
  3. 选择安装到 Macintosh HD
  4. 耐心等待,过程较为漫长

6. 完成安装

安装完成后,剩余步骤为初始化新的 MacOS 系统流程。

7 - MySQL 常用 SQL 语句速查

MySQL 常用 SQL 语句速查,涵盖数据库、数据表、数据行的增删改查及常用数据类型。

数据库操作

/* 创建数据库 */
CREATE DATABASE 数据库名称;

/* 删除数据库 */
DROP DATABASE 数据库名称;

/* 查看所有数据库 */
SHOW DATABASES;

/* 查看当前数据库的字符集等信息 */
SHOW CREATE DATABASE 数据库名称;

/* 修改数据库的字符集等属性 */
ALTER DATABASE 数据库名称 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

数据表操作

/* 创建数据表 */
CREATE TABLE 数据表名称 (字段1 数据类型1, 字段2 数据类型2, ...);

/* 删除数据表 */
DROP TABLE 数据表名称;

/* 查看当前数据库中的所有数据表 */
SHOW TABLES;

/* 查看数据表的结构 */
DESCRIBE 数据表名称;

/* 查看数据表的创建语句 */
SHOW CREATE TABLE 数据表名称;

/* 添加新列 */
ALTER TABLE 数据表名称 ADD COLUMN 新字段 数据类型;

/* 修改列的数据类型 */
ALTER TABLE 数据表名称 MODIFY COLUMN 字段1 新数据类型;

/* 重命名列 */
ALTER TABLE 数据表名称 CHANGE COLUMN 字段1 新字段名 数据类型;

/* 删除列 */
ALTER TABLE 数据表名称 DROP COLUMN 字段1;

数据行操作

/* 插入数据行 */
INSERT INTO 数据表名称 (字段1, 字段2, ...) VALUES (1, 2, ...);

/* 查询数据行 */
SELECT 字段1, 字段2, ... FROM 数据表名称 WHERE 字段1 = '条件值1';

/* 更新数据行 */
UPDATE 数据表名称 SET 字段1 = '新值1', 字段2 = '新值2', ... WHERE 字段1 = '条件值1';

/* 删除数据行 */
DELETE FROM 数据表名称 WHERE 字段1 = '条件值1';

条件与排序

/* 条件查询 */
SELECT * FROM 数据表 WHERE 字段1 = '值';
SELECT * FROM 数据表 WHERE 字段1 LIKE '%关键词%';
SELECT * FROM 数据表 WHERE 字段1 > 100 AND 字段2 = '值';

/* 排序 */
SELECT * FROM 数据表 ORDER BY 字段1 DESC;        /* 降序 */
SELECT * FROM 数据表 ORDER BY 字段1 ASC;         /* 升序(默认) */

/* 分页 */
SELECT * FROM 数据表 LIMIT 10;                    /* 取前 10 条 */
SELECT * FROM 数据表 LIMIT 10 OFFSET 20;          /* 跳过 20 条,取 10 条 */
SELECT * FROM 数据表 LIMIT 20, 10;                /* 同上,简写形式 */

聚合与分组

/* 聚合函数 */
SELECT COUNT(*) FROM 数据表;                      /* 统计行数 */
SELECT SUM(金额字段) FROM 数据表;                  /* 求和 */
SELECT AVG(价格字段) FROM 数据表;                  /* 平均值 */
SELECT MAX(年龄字段) FROM 数据表;                  /* 最大值 */
SELECT MIN(年龄字段) FROM 数据表;                  /* 最小值 */

/* 分组统计 */
SELECT 分类字段, COUNT(*) FROM 数据表 GROUP BY 分类字段;
SELECT 分类字段, SUM(金额) FROM 数据表 GROUP BY 分类字段 HAVING SUM(金额) > 1000;

索引

/* 创建索引 */
CREATE INDEX 索引名称 ON 数据表 (字段1);
CREATE INDEX 索引名称 ON 数据表 (字段1, 字段2);   /* 联合索引 */

/* 删除索引 */
DROP INDEX 索引名称 ON 数据表;

/* 查看索引 */
SHOW INDEX FROM 数据表;

用户管理

/* 创建用户 */
CREATE USER '用户名'@'localhost' IDENTIFIED BY '密码';
CREATE USER '用户名'@'%' IDENTIFIED BY '密码';     /* 允许远程登录 */

/* 授权 */
GRANT ALL PRIVILEGES ON 数据库名.* TO '用户名'@'localhost';
GRANT SELECT, INSERT, UPDATE ON 数据库名.* TO '用户名'@'%';

/* 刷新权限 */
FLUSH PRIVILEGES;

/* 查看用户 */
SELECT User, Host FROM mysql.user;

/* 修改密码 */
ALTER USER '用户名'@'localhost' IDENTIFIED BY '新密码';

/* 删除用户 */
DROP USER '用户名'@'localhost';

常用数据类型

数值类型

数据类型说明取值范围适用场景
INT普通整数−21亿 ~ 21亿用户ID、文章数量、年份
BIGINT大整数−922亿亿 ~ 922亿亿订单号、日志ID、超大数据量
FLOAT单精度浮点数约 7 位有效数字科学计算、百分比
DOUBLE双精度浮点数约 15 位有效数字科学计算、高精度要求
DECIMAL定点数(精确)取决于定义金额、价格(必须用这个,避免精度丢失)

FLOAT(M,D) / DOUBLE(M,D) / DECIMAL(M,D) 中的 (M,D) 表示总长度 M 位,其中 D 位是小数。例如 DECIMAL(10,2) 总长 10 位,小数 2 位,整数 8 位。

字符串类型

数据类型说明最大长度适用场景
VARCHAR可变长度字符串65535 字符用户名、邮箱、标题(短文本首选)
TEXT长文本65535 字符文章正文、评论内容、日志详情

日期和时间类型

数据类型说明取值范围适用场景
DATETIME日期和时间1000 ~ 9999 年创建时间、更新时间(通用场景)
TIMESTAMP时间戳1970 年起记录日志时间,受时区影响(自动转换为当前时区)

DATETIMETIMESTAMP 的区别:TIMESTAMP 会自动转换为当前时区;DATETIME 不受时区影响。日常场景首选 DATETIME

JSON 类型

数据类型说明适用场景
JSON存储 JSON 格式数据配置信息、动态属性、非结构化数据存储

8 - Docker 常用命令速查

日常使用频率最高的 Docker 命令和配置文件说明。

列出日常使用频率最高的命令。更多可参考 Docker 命令大全 | 菜鸟教程

容器管理

命令说明
docker ps列出运行中的容器
docker ps -a列出所有容器(含已停止的)
docker start <容器>启动已停止的容器
docker stop <容器>停止运行中的容器
docker restart <容器>重启容器
docker rm <容器>删除已停止的容器
docker rm -f <容器>强制删除运行中的容器
docker rename <容器> <新名称>重命名容器

镜像管理

命令说明
docker images列出本地镜像
docker pull <镜像名>从仓库拉取镜像,如 docker pull nginx
docker rmi <镜像名>删除本地镜像
docker build -t <标签> .构建镜像,-t 指定名称和标签
docker tag <镜像> <新标签>给镜像打标签
docker push <镜像名>推送镜像到远程仓库

日志与调试

命令说明
docker logs <容器>查看容器日志
docker logs -f --tail 100 <容器>实时查看最近 100 条日志
docker exec -it <容器> bash进入容器内部(交互式 Shell)
docker inspect <容器>查看容器的详细信息(JSON)
docker stats实时显示容器资源占用(CPU/内存)
docker top <容器>查看容器内运行的进程

Docker Compose

命令说明
docker compose up -d后台启动所有服务
docker compose down停止并移除所有容器和网络
docker compose ps列出项目中的容器状态
docker compose logs -f实时查看所有服务的日志
docker compose restart重启所有服务
docker compose pull拉取所有服务的最新镜像

系统维护

命令说明
docker system df查看磁盘使用情况
docker system prune清理未使用的容器、镜像、网络
docker system prune -a清理所有未使用的资源(含未使用的镜像)
docker info查看 Docker 系统信息

9 - Linux 常用命令速查

日常使用频率最高的 Linux 命令速查表,涵盖文件操作、进程管理、磁盘网络、权限系统等场景。

列出日常使用频率最高的命令。更多可参考 Linux 命令大全 | 菜鸟教程

系统信息

命令说明
uname -a显示操作系统名称、内核版本、主机名等详细信息
who -b显示系统上次启动时间
uptime显示系统运行时长和负载
hostnamectl查看或修改主机名
shutdown -h now立即关机
shutdown -h 1010 分钟后关机
reboot重启服务器

文件与目录

命令说明
pwd显示当前工作目录
cd <路径>切换目录
ls列出当前目录的文件和子目录
ls -la列出所有文件(含隐藏文件)及详细信息
mkdir <目录名>创建目录
rmdir <目录名>删除空目录
cp <源> <目标>复制文件或目录
mv <源> <目标>移动或重命名
rm <文件>删除文件
rm -rf <目录>强制递归删除目录(慎用)
touch <文件>创建空文件或更新文件时间戳
cat <文件>查看文件全部内容
less <文件>分页查看文件内容(按 q 退出)
head -n 20 <文件>查看文件前 20 行
tail -n 20 <文件>查看文件最后 20 行
tail -f <文件>实时追踪文件新增内容(如日志)

文件查找与内容搜索

命令说明
find <目录> -name "*.py"按文件名递归查找
grep "关键词" <文件>在文件中搜索文本
grep -r "关键词" <目录>递归搜索目录下所有文件
wc <文件>统计文件行数、单词数、字节数
wc -l <文件>仅统计文件行数
sort <文件>对文件内容排序

进程管理

命令说明
ps aux查看所有运行中的进程
ps -ef查看所有进程(另一格式)
top实时显示进程和系统资源占用
htoptop 的增强版(需安装)
kill <PID>终止指定进程
kill -9 <PID>强制终止进程
nohup <命令> &后台运行命令(退出终端后继续)

磁盘与内存

命令说明
df -h查看磁盘分区使用情况(人类可读)
du -sh <目录>查看目录总大小
free -h查看内存使用情况
free -m以 MB 为单位显示内存

网络

命令说明
ping <地址>测试网络连通性
curl <URL>发送 HTTP 请求
wget <URL>下载文件
ss -tlnp查看监听端口和对应进程
netstat -tlnp查看监听端口(ss 的替代)
ip addr查看网络接口和 IP 地址
ifconfig查看网络配置(需安装 net-tools)

文件权限

命令说明
chmod 755 <文件>设置文件权限
chmod +x <文件>给文件添加可执行权限
chown <用户>:<组> <文件>修改文件所属用户和组

压缩与归档

命令说明
tar -czf 包名.tar.gz <目录>打包并压缩为 tar.gz
tar -xzf 包名.tar.gz解压 tar.gz
unzip <文件>.zip解压 zip 文件
zip -r 包名.zip <目录>压缩为 zip

包管理(Debian/Ubuntu)

命令说明
apt update更新软件包索引
apt upgrade升级所有可升级的软件包
apt install <包名>安装软件包
apt remove <包名>卸载软件包
apt search <关键词>搜索软件包

10 - Docker 重启策略详解

Docker 容器的重启策略有四种:noalwayson-failureunless-stopped

情况noalwayson-failureunless-stopped
容器正常退出 (0 状态)不重启重启不重启重启
容器非正常退出 (非 0 状态)不重启重启重启重启
手动停止 (docker stop)不重启不重启不重启不重启
Docker 服务重启 (如系统重启)不重启重启不重启不重启

下面通过一个 demo 来演示它们的区别。

准备测试环境

创建一个名为 test.sh 的脚本,5 秒后自动退出:

#!/bin/bash
sleep 5
exit 1

创建 Dockerfile 将其打包进镜像:

FROM ubuntu
ADD test.sh /
CMD /bin/bash /test.sh

构建镜像:

docker build -t test-restart .

no

docker run -d --name=test-restart-no test-restart

容器 5 秒后退出,docker daemon 不做任何处理。

结论:容器退出后不重启。

always

docker run -d --restart=always --name=test-restart-always test-restart

容器退出后 docker daemon 自动重启。虽然每次生命周期只有 5 秒,但不断重启,表面上像一直在运行。

如果手动 docker stop 停止,不会自动重启。但重启 Docker daemon 后,容器会再次启动。

结论:除非手动停止,否则总是重启。重启 Docker daemon 也会触发。

on-failure

docker run -d --restart=on-failure:3 --name=test-restart-on-failure test-restart

容器退出后触发重启。容器退出后触发重启。当重启达到 3 次上限后不再重启。

注意:Docker 认为容器成功启动至少需运行 10 秒。脚本 5 秒就退出,触发重启的次数会持续累加直到上限(参考Docker 官方文档)。

结论:仅在容器非正常退出时重启,可设置最大重试次数。

unless-stopped

docker run -d --restart=unless-stopped --name=test-restart-unless-stopped test-restart

表现和 always 一样——容器退出后自动重启。区别在于:手动 docker stop 停止后,重启 Docker daemon 时容器不会自动启动,而 always 会。

结论:与 always 类似,但手动停止后重启 Docker 不会再次启动。

如何选择

  • no:一次性任务、调试环境,不需要自动重启
  • always:Web 服务、数据库等需要持续运行的服务
  • on-failure:脚本任务、批处理作业,只在出错时重试
  • unless-stopped:和 always 类似,但希望手动停止后不再被 Docker 重启时使用

参考资料

11 - Git 常用命令速查

日常使用频率最高的 Git 命令速查表,涵盖基本操作、分支管理、查看历史、撤销与暂存、远程协作等场景。

本文基于 Git 2.46.0,日常使用中如有更多需求可查看 git help 或官方文档。

基本操作

命令说明
git init在当前目录初始化一个新的 Git 仓库
git clone <地址>克隆远程仓库到本地
git add .暂存所有修改过的文件
git add <文件>暂存指定文件
git commit -m "说明"提交暂存区的内容
git commit -am "说明"暂存所有已跟踪文件并提交(跳过 git add
git status查看当前工作区状态

分支管理

命令说明
git branch列出本地分支(当前分支前有 *
git branch -a列出所有分支(含远程分支)
git branch <名称>创建新分支
git branch -d <名称>删除已合并的分支
git branch -D <名称>强制删除分支(即使未合并)
git switch <名称>切换到已有分支
git switch -c <名称>创建并切换到新分支
git merge <分支>将指定分支合并到当前分支
git rebase <分支>将当前分支变基到指定分支

查看历史

命令说明
git log查看提交历史
git log --oneline单行显示提交历史
git log --oneline --graph以图形方式显示分支历史
git log -p显示每次提交的 diff
git diff比较工作区和暂存区的差异
git diff --staged比较暂存区和上次提交的差异
git show查看最新提交的详细信息
git show <commit-id>查看指定提交的详细信息

撤销与暂存

命令说明
git restore <文件>撤销工作区的修改(未暂存的文件)
git restore --staged <文件>取消暂存(文件回到工作区)
git reset --soft HEAD~1撤销上次提交,保留修改
git reset --hard HEAD~1撤销上次提交,丢弃修改(慎用)
git stash暂存当前工作区的修改
git stash pop恢复最近一次暂存并删除它
git stash list查看暂存列表

远程协作

命令说明
git remote -v查看远程仓库地址
git remote add origin <地址>添加远程仓库
git push origin <分支>推送代码到远程
git push -u origin <分支>首次推送并建立 upstream 关联
git pull拉取远程代码并合并
git fetch拉取远程代码但不合并
git clone <地址>克隆远程仓库

配置

命令说明
git config --list查看当前所有配置
git config --global user.name "名称"设置全局用户名
git config --global user.email "邮箱"设置全局邮箱
git config user.name "名称"设置当前仓库的用户名
git config user.email "邮箱"设置当前仓库的邮箱
git config --global http.proxy <地址>设置 HTTP 代理
git config --global --unset http.proxy取消 HTTP 代理

其他

命令说明
git tag列出所有标签
git tag <名称>创建轻量标签
git mv <旧文件> <新文件>重命名或移动文件
git rm <文件>从仓库中删除文件
git clean -df删除未跟踪的文件和目录
git help查看 Git 帮助信息
git -v查看 Git 版本

12 - Docker 远程管理 Portainer

通过 Portainer 的 Web 界面远程管理多台主机的 Docker 容器。
2024-10-08 update 安全提醒

直接暴露 Docker API 端口(2375)到公网没有任何加密和认证。配置完成后务必限制防火墙来源 IP,或配置 TLS 加密。否则可能被加密劫持蠕虫盯上。

配置好远程管理后不久,我收到了云服务器恶意文件通知,并在远程主机中发现了一个莫名的容器 boorish_agelast,运行着 ubuntu:18.04。经确认是针对 Docker 守护进程的加密劫持蠕虫 Cetus。如果你的 Docker 环境不需要频繁集中管理,建议先配置好 TLS 加密再开放远程端口:

本文内容基于 6053537/portainer-ce - Docker Image | Docker Hub 的汉化版。

远程主机设置

  1. 确保远程主机已安装 Docker

  2. 进入主机终端,输入命令:

nano /usr/lib/systemd/system/docker.service
  1. 然后做以下修改:
# 将这一行
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

# 改为这样
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock
  1. 最后再重启 Docker 即可
systemctl daemon-reload
systemctl restart docker
  1. 记得在服务器的防火墙放开 2375 端口

Portainer 设置

  1. 环境 - 添加环境 - 独立的 Docker
  2. 选择 API 连接模式
  3. Docker API URL 处填写被远程连接的主机 IP+ 端口,如 6.6.6.6:2375
  4. 点击链接,完成。

参考资料

13 - Git 清理远端仓库全部提交历史

删除 Git 仓库全部提交历史但保留仓库本身,适用于清理隐私信息或给仓库瘦身。
注意

此操作不可逆,会永久删除仓库的所有提交历史,请提前做好备份。

背景

当提交记录中包含隐私信息(如密钥、密码),或仓库因上传大量文件导致体积过大、拉取频繁出错时,可以通过清除全部提交历史来"瘦身"仓库,同时保留仓库本身(Star、Issues 等不受影响)。

以下两种方法均以 main 分支为例,操作前请先将仓库克隆到本地。

方法一:创建空白分支替换

通过 --orphan 创建一个没有历史的新分支,替换掉原来的 main

git checkout --orphan latest_branch  # 创建一个没有历史的新分支
git add -A  # 暂存所有文件
git commit -m "Initial commit"  # 创建初始提交
git branch -D main  # 删除本地的 main 分支
git branch -m main  # 将当前分支重命名为 main
git push -f origin main  # 强制推送到远程仓库,替换远程 main 分支

方法二:删除 .git 重新初始化

直接删除本地的 Git 历史,重新初始化一个全新的仓库:

rm -rf .git  # 删除本地 Git 仓库目录
git init  # 重新初始化一个新的 Git 仓库
git add -A  # 暂存所有文件
git commit -m "Initial commit"  # 创建初始提交
git push -f https://github.com/username/repo.git main  # 强制推送到远程仓库(需替换为实际仓库地址)
两种方法的区别
  • 方法一保留了本地 Git 配置(如 remote、branch tracking),操作更简单
  • 方法二完全重置仓库,但需要手动填写远程仓库地址,且会丢失所有本地 Git 配置

参考资料

14 - Git 多仓库身份配置

在个人项目和公司项目中使用不同的 Git 用户名和邮箱提交,避免身份混淆。

工作电脑上同时有个人项目和公司项目时,如果不做配置,所有提交都会使用同一个用户名和邮箱。这篇文章教你如何让 Git 根据仓库自动切换身份。

配置优先级

Git 采用三层配置覆盖,优先级从低到高

系统级 → 全局级 → 仓库级

仓库级配置会覆盖全局级,所以只需要在个别仓库设置独立身份即可。

操作步骤

1. 设置全局默认身份

适用于大多数仓库(比如你的个人项目):

git config --global user.name "your-name"
git config --global user.email "your@email.com"

2. 设置单个仓库的独立身份

终端切换到需要单独设置的仓库目录,不加 --global

cd /path/to/company-project
git config user.name "work-name"
git config user.email "work@company.com"

这条命令会写入当前仓库的 .git/config,只影响这个仓库。

3. 验证当前仓库身份

git config user.name
git config user.email

手动编辑配置

也可以直接打开仓库下的 .git/config 文件,找到或添加:

[user]
    name = work-name
    email = work@company.com

常见场景

场景全局身份仓库级身份
个人 GitHub 项目 + 公司 GitLab 项目个人邮箱公司邮箱
开源项目 + 内部项目个人昵称公司实名
多个账号的 GitHub主账号副账号