Git查看本地分支

Git查看本地分支

引言

多人协作久了本地会攒下一堆分支,切分支前先看清当前在哪个分支、有哪些本地分支、哪些已合并。git branch是基础命令,配合不同参数能看本地、远程、合并状态。

列出本地分支

git branch

列出所有本地分支,当前分支前面带*号高亮,一眼定位自己在哪条线上。

看当前所在分支

git branch --show-current

只输出当前分支名,写脚本时取这个最干净,不用从整行结果里截取。

列出远程分支

git branch -r

只列远程跟踪分支;想看本地加远程全部用-a。

查看最后一次提交

git branch -v

每个分支后面跟最近一次提交的短hash和说明,判断分支是否还在推进。

看已合并到当前分支的分支

git branch --merged
git branch --no-merged

merged列出已并入当前线、可安全删除的分支;no-merged是还没并入、删之前要小心的。

查分支对应提交

git branch -vv

额外显示本地分支跟踪的远程分支和 ahead/behind 数量,看本地是否落后远程。

注意事项

  • git branch只看本地,远程分支要先fetch刷新;
  • 带*的是当前分支,别在错误分支上提交;
  • --merged里的分支可放心删,no-merged删前确认有无保留价值;
  • 删除已合并分支用git branch -d,未合并强删用-D;
  • 分支命名按feature/修复类型规范,方便批量清理;
  • 定期删过期本地分支,避免列表臃肿。

总结

git branch列本地并标当前分支,--show-current只取当前名,-r看远程,-v看各分支最新提交,--merged和--no-merged判断可否安全删除,-vv看跟踪关系和领先落后。切分支前先确认当前线,远程信息先fetch,已合并分支用-d安全删,未合并慎删,定期清理过期本地分支保持仓库清爽。


emer 发布于  2026-10-20 07:09 

Linux查看系统版本

Linux查看系统版本

引言

接手一台服务器,第一件事是搞清楚发行版是CentOS、Ubuntu还是Debian、内核多少位、版本号多少,因为包管理器、软件源、命令差异都跟发行版绑定。下面几组命令覆盖发行版、内核、架构三个维度。

看发行版版本(推荐)

cat /etc/os-release

现代发行版通用,输出NAME、VERSION、PRETTY_NAME,CentOS、Ubuntu、Debian都适用。

看CentOS具体版本

cat /etc/redhat-release
# 或
rpm -q centos-release

RHEL系专用,直接显示CentOS Linux 7/8等版本号。

看Ubuntu/Debian版本

lsb_release -a
# 或
cat /etc/debian_version

lsb_release显示Distributor和Release,没装时读debian_version兜底。

看内核版本

uname -r
# 完整信息
uname -a

-r看内核版本号,-a连架构、主机名、编译时间一起输出。

看CPU架构

arch
# 或
uname -m

x86_64是64位,aarch64是ARM,选安装包时必须对应。

看系统位数和硬件

getconf LONG_BIT

输出32或64,比uname更直接回答多少位。

注意事项

  • 发行版和内核是两回事,Ubuntu 22.04可以换内核;
  • 包管理器按发行版选:CentOS用yum/dnf,Ubuntu用apt;
  • 容器内cat /etc/os-release看到的是镜像版本,不是宿主机;
  • 老系统可能没有os-release,用redhat-release或issue兜底;
  • 生产升级内核前先uname -r记录当前版本便于回退;
  • 脚本里判断发行版读/etc/os-release的ID字段最稳。

总结

cat /etc/os-release看通用发行版,redhat-release看CentOS,lsb_release看Ubuntu,uname -r看内核,arch/uname -m看架构,getconf LONG_BIT看位数。先分清发行版和内核,包管理器按发行版选,容器内读到的是镜像版本,脚本判断优先解析os-release的ID字段,升级内核前记录当前版本方便回退。


emer 发布于  2026-10-20 07:08 

Docker停止删除容器

Docker停止删除容器

引言

容器用多了会堆积一堆停止状态的旧实例,占磁盘、干扰排查。停止和删除是两步:先停再删,生产环境删容器前要确认数据已持久化,否则删除即丢失。

停止单个容器

docker stop 容器名或ID

发送SIGTERM优雅停止,等待默认10秒,超时再发SIGKILL强杀。

强制停止

docker kill 容器名或ID

直接SIGKILL,不给进程清理机会,只用于卡死不响应的容器。

删除已停止容器

docker rm 容器名或ID

只能删停止状态的容器,运行中需先stop或加-f。

强制删除运行中容器

docker rm -f 容器名或ID

一步停止并删除,慎用,等价于kill后rm。

批量清理

# 删除所有已停止容器
docker container prune

# 删除全部容器(含运行中,危险)
docker rm -f $(docker ps -aq)

prune只清停止的,相对安全;ps -aq配合rm -f会删光,生产禁止随手执行。

启动与重启

docker start 容器名
docker restart 容器名

停止的容器start可再次拉起,文件系统内改动仍在,只有删容器才清除。

注意事项

  • 删除容器前确认挂载卷和数据,容器内非挂载目录删除即丢;
  • 数据库容器先备份再删,别以为能找回来;
  • -f强制删除跳过优雅停止,可能丢未刷盘数据;
  • 批量命令先docker ps -aq列出确认,再删;
  • 加了--rm的容器退出自动删除,不留残骸;
  • 清理容器不影响镜像,镜像还在可随时重建。

总结

docker stop优雅停止,docker kill强杀,docker rm删已停容器,-f强制删运行中容器,container prune批量清停止实例。核心原则是先确认数据挂载和备份再删,生产慎用rm -f全量清理,执行批量命令前先列出ID核对,理解容器删除会清空非挂载层数据。


emer 发布于  2026-10-20 07:07 

MySQL查看表索引

MySQL查看表索引

引言

排查慢查询、判断索引是否生效前,先要搞清楚一张表上到底建了哪些索引、每个索引包含哪些列、是不是唯一索引。SHOW INDEX和information_schema都能查,前者直观,后者适合脚本批量统计。

SHOW INDEX查看索引

SHOW INDEX FROM users;

列出users表全部索引,Key_name是索引名,Column_name是索引列,Seq_in_index是列在联合索引里的顺序,Non_unique为0表示唯一索引。

重点字段含义

  • Key_name:索引名,PRIMARY是主键;
  • Seq_in_index:联合索引中的列顺序,最左前缀从这里判断;
  • Column_name:该索引包含的列;
  • Non_unique:0唯一,1普通;
  • Sub_part:前缀索引长度;
  • Cardinality:基数,越接近总行数区分度越好。

建表语句里看索引

SHOW CREATE TABLE users\G

直接看完整建表语句,KEY和UNIQUE KEY就是索引定义,适合快速人工核对。

information_schema批量查

SELECT table_name, index_name, column_name, seq_in_index, non_unique
FROM information_schema.statistics
WHERE table_schema = 'mydb'
ORDER BY table_name, index_name, seq_in_index;

一次性导出整库所有表的索引结构,做索引巡检和冗余分析。

查某列是否被索引覆盖

SELECT DISTINCT index_name FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='users' AND column_name='phone';

判断phone列有没有索引,决定查询能否走索引。

注意事项

  • 联合索引顺序决定最左前缀,别只看有没有建;
  • Cardinality是估算值,会随ANALYZE TABLE刷新;
  • 前缀索引Sub_part只索引前N个字符;
  • 重复冗余索引用pt-duplicate-key-checker之类工具清理;
  • 索引不是越多越好,写多表要权衡插入成本;
  • 查完索引再配合EXPLAIN看实际是否命中。

总结

SHOW INDEX FROM表看索引明细,SHOW CREATE TABLE看定义,information_schema.statistics批量导出整库索引。重点关注索引名、列顺序、唯一性和基数,联合索引按最左前缀使用,建完索引务必用EXPLAIN验证是否真正命中,定期清理重复冗余索引,避免写放大。


emer 发布于  2026-10-20 07:06 

PHP字符串反转方法

PHP字符串反转方法

引言

字符串反转是面试和笔试高频小题,业务里也常用于生成验证码、翻转密文顺序、做简单加密。PHP内置strrev一行搞定,但处理中文时要注意字节和字符的区别。

英文字符反转:strrev

$str = "hello world";
echo strrev($str); // dlrow olleh

strrev按字节反转,英文和数字没有问题,性能也最高。

中文字符串反转

strrev直接转中文会乱码,因为中文UTF-8占3个字节,按字节切会把一个字拆坏。需要按字符处理:

$str = "技术分享";
$len = mb_strlen($str, 'UTF-8');
$result = '';
for ($i = $len - 1; $i >= 0; $i--) {
    $result .= mb_substr($str, $i, 1, 'UTF-8');
}
echo $result; // 享分术技

用mb_strlen取字符数,mb_substr按字符回取,保证每个完整汉字不被拆开。

数组方式实现

$arr = preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
echo implode('', array_reverse($arr));

u修饰符按UTF-8切字符成数组,array_reverse翻转后再拼回去。

随机打乱:str_shuffle

echo str_shuffle("abc123"); // 每次结果随机

注意str_shuffle同样按字节,中文打乱不适用,验证码里建议只放英文数字。

注意事项

  • strrev只适合单字节英文,中文必须走mb系列;
  • 生产验证码用str_shuffle后再截取长度,别用中文;
  • 反转不等于加密,明文可还原,别拿来做真正加密;
  • mb扩展缺失时先检查extension_loaded('mbstring');
  • 超大字符串循环回拼建议用数组收集后implode,减少字符串反复复制。

总结

英文用strrev一行反转,中文用mb_strlen加mb_substr按字符倒取,数组preg_split配合array_reverse也能实现,随机打乱用str_shuffle但仅限英文数字。记住字节反转和字符反转的区别,中文场景务必走mb扩展,大字符串用数组收集再拼接提升性能。


emer 发布于  2026-10-20 07:05 

Nginx配置检查测试

Nginx配置检查测试

引言

改完Nginx配置直接reload最容易踩坑:语法错、证书路径错、端口被占会导致Nginx起不来甚至站点全挂。规范流程是先检查语法,通过后再平滑重载,出问题能快速回退。

语法检查

nginx -t

检查默认配置文件语法,输出syntax ok和test is successful才说明配置无误。

指定配置文件检查

nginx -t -c /etc/nginx/nginx.conf

自定义路径时用-c指定,避免检查错文件。

平滑重载

nginx -s reload

不中断现有连接重新加载配置,改动生效不宕机。

查看编译参数和版本

nginx -V

大写V看版本和编译模块,确认是否包含ssl、gzip、stream等模块。

打印生效配置

nginx -T

大写T会把所有include进来的配置打印出来,排查重复server或覆盖时用。

出错常见原因

  • 括号不配对、分号漏写;
  • 证书key路径不存在或权限600不对;
  • listen端口已被其他进程占用;
  • upstream后端地址写错;
  • include路径下的文件本身语法错。

注意事项

  • 永远先-t再reload,禁止跳过检查;
  • 改配置前备份原文件,出错可立刻回退;
  • -T输出很长,重定向到文件再查;
  • reload失败先看error.log定位行号;
  • 生产环境改完curl本机验证再放行;
  • 多台机器逐台灰度,不要一次全改。

总结

nginx -t检查语法,-c指定文件,-s reload平滑生效,-V看编译模块,-T打印完整配置。铁律是先检查通过再重载,改前备份、出错看error.log、本机curl验证后再上线,生产逐台灰度,避免一次改全量导致整站不可用。


emer 发布于  2026-10-19 07:39 

MySQL查看数据库列表

MySQL查看数据库列表

引言

刚连上一台MySQL服务器,先要看实例上有哪些库、当前账号能访问哪些库。SHOW DATABASES是最基础的入口,配合information_schema可拿到库名、字符集、容量等完整信息。

列出所有数据库

SHOW DATABASES;

列出当前账号有权限看到的全部库,看不到的库是权限不足,不代表不存在。

查看当前所在库

SELECT DATABASE();

切换库之前先确认当前连接落在哪个库,避免写SQL操作错库。

切换数据库

USE mydb;

切库后后续不加库名的表操作都落在mydb。

查库字符集和排序规则

SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA;

拿到每个库的默认字符集,排查乱码时先看这里。

查看库占用空间

SELECT table_schema,
       ROUND(SUM(data_length+index_length)/1024/1024,2) AS size_mb
FROM information_schema.tables
GROUP BY table_schema
ORDER BY size_mb DESC;

按库汇总数据和索引大小,快速找出占空间大户。

注意事项

  • SHOW DATABASES只显示有权限的库,根账号才看全;
  • information_schema是系统库,不要往里写业务数据;
  • 新库建库时指定utf8mb4,避免emoji乱码;
  • 删库DROP DATABASE不可逆,先备份再操作;
  • 多实例用端口区分,别把实例和库混淆;
  • 脚本里用SELECT SCHEMA_NAME批量遍历,比SHOW好解析。

总结

SHOW DATABASES列库,SELECT DATABASE()看当前库,USE切库,information_schema.SCHEMATA查字符集,按table_schema聚合查容量。先确认当前库再写SQL,建库统一utf8mb4,删库前务必备份,脚本批量处理优先走information_schema。


emer 发布于  2026-10-19 07:38 

PHP时间戳转日期

PHP时间戳转日期

引言

数据库里常存Unix时间戳(秒级整数),展示到页面要转成可读日期;反过来用户选的日期也要转成时间戳入库。date()和strtotime()是这对基础转换工具,理解格式符和时区才能避免差8小时。

时间戳转日期

$ts = 1760000000;
echo date('Y-m-d H:i:s', $ts);

date()第二个参数缺省就是当前时间time(),传指定时间戳则格式化该时刻。

当前时间戳

echo time();            // 秒级时间戳
echo microtime(true);   // 带微秒的浮点时间戳

日期字符串转时间戳

$ts = strtotime('2026-10-19 08:30:00');
echo $ts;

strtotime支持英文相对表达式:

strtotime('tomorrow');
strtotime('+1 week');
strtotime('next Monday');

DateTime面向对象写法

$dt = new DateTime('@' . $ts);
echo $dt->format('Y-m-d H:i:s');

$d = DateTime::createFromFormat('Y-m-d', '2026-10-19');
echo $d->getTimestamp();

复杂时区和格式解析用DateTime更稳。

常用格式符

  • Y四位年,m两位月,d两位日,H24小时,i分,s秒;
  • 带毫秒用v,星期用D/l,12小时制用g/a。

注意事项

  • 服务器时区不对会差8小时,先date_default_timezone_set('Asia/Shanghai');
  • date()对1970前或2038前后32位系统有边界问题;
  • strtotime解析失败返回false,要判空再用;
  • 毫秒时间戳除以1000再传给date();
  • 跨时区存储建议统一UTC,展示时再转本地;
  • MySQL存int(10)秒级,避免用字符串日期做比较。

总结

时间戳转日期用date('Y-m-d H:i:s', $ts),日期转时间戳用strtotime(),复杂解析用DateTime。先设好Asia/Shanghai时区,毫秒先除以1000,strtotime失败要判空。入库统一存秒级时间戳,展示层再格式化,比存字符串日期更好比较和索引。


emer 发布于  2026-10-19 07:37 

Docker查看运行容器

Docker查看运行容器

引言

部署多个服务后,先要看清哪些容器在跑、状态如何、映射了哪些端口、跑了多久。docker ps系列命令是日常运维入口,配合格式化和过滤快速定位目标容器。

只看运行中容器

docker ps

输出容器ID、镜像、命令、创建时间、状态、端口映射、名称,默认只列正在运行的。

查看全部容器(含已停止)

docker ps -a

把Exited状态的容器也列出来,排查退出残留时用。

只看容器ID

docker ps -q

输出纯ID,配合批量停止删除。

自定义输出列

docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"

只保留关心的列,脚本采集更清晰。

按镜像过滤

docker ps --filter ancestor=nginx:latest

列出指定镜像启动的容器。

查看容器资源占用

docker stats

实时看每个容器CPU、内存、网络IO,Ctrl+C退出。

注意事项

  • ps默认不含已停止容器,找退出容器用-a;
  • STATUS显示Up时长或Exited码,退出码非0要查日志;
  • PORTS列看清宿主端口到容器端口的映射;
  • 容器名重复会冲突,--name要唯一;
  • 配合docker inspect看单个容器完整配置;
  • 批量操作前先用-q列出ID确认范围。

总结

docker ps看运行中容器,-a含已停止,-q取ID批量处理,--format自定义列,--filter按镜像过滤,docker stats看实时资源。运维先列清单确认状态和端口,再决定停止、重启或排查,避免凭印象操作容器。


emer 发布于  2026-10-19 07:36 

Nginx默认站点配置

Nginx默认站点配置

引言

直接用IP或未匹配到server_name的域名访问时,Nginx会落到默认站点。装好Nginx自带的欢迎页就是默认server,安全上建议改掉,避免暴露版本或被扫描利用。

默认站点如何确定

同一端口下,第一个server块、或带default_server标记的就是默认站点:

server {
    listen 80 default_server;
    server_name _;
    root /usr/share/nginx/html;
    index index.html;
}

server_name用_占位,表示匹配任意未命中的主机名。

配置占位拒绝页

对外只暴露正式站点时,默认站点直接返回444或简单403:

server {
    listen 80 default_server;
    server_name _;
    return 444;
}

444是Nginx特有,直接断开连接,不返回内容。

隐藏版本号

http {
    server_tokens off;
}

避免错误页暴露Nginx版本,减少针对性漏洞扫描。

自定义默认首页

server {
    listen 80 default_server;
    server_name _;
    root /var/www/default;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

多端口默认

HTTPS同理,443也要配default_server:

server {
    listen 443 ssl default_server;
    server_name _;
    # 自签或占位证书,否则握手失败
    return 444;
}

注意事项

  • 一台机器同端口只能有一个default_server;
  • 不配默认站,未匹配域名会落到第一个server,可能串站点;
  • 改完nginx -t校验再reload;
  • 云主机IP直扫建议默认站返回444,不暴露首页;
  • 区分default_server和servername ,前者是优先级标记;
  • SSL默认站必须有证书,否则浏览器握手报错。

总结

默认站点由default_server或同端口首个server决定,用server_name _占位。安全做法是把默认站返回444拒绝、server_tokens off隐藏版本,443也要配默认拒绝站,避免IP直扫串到正式站点。改完务必-t校验再reload。


emer 发布于  2026-10-19 07:35 

MySQL查看表结构

MySQL查看表结构

引言

接手老库、写SQL、加字段前,先看清表里有哪些列、类型、主键、索引和默认值。DESC看字段概览,SHOW CREATE TABLE拿到完整建表语句,information_schema可批量查元数据。

DESC看字段概览

DESC users;
-- 等价
DESCRIBE users;

输出Field、Type、Null、Key、Default、Extra六列,快速看字段类型和是否主键。

完整建表语句

SHOW CREATE TABLE users;

拿到原始CREATE TABLE,包含引擎、字符集、索引、外键、注释,迁移和备份最有用。

查看表索引

SHOW INDEX FROM users;

看有哪些索引、唯一性、列顺序,分析慢查询时用。

查表状态和引擎

SHOW TABLE STATUS LIKE 'users';

看引擎、行数、行格式、数据和索引大小、自增值。

information_schema批量查

SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='dbname' AND TABLE_NAME='users';

程序里动态读表结构、批量比对字段时用。

注意事项

  • DESC不显示完整索引和外键,要看SHOW CREATE TABLE;
  • 大表SHOW TABLE STATUS的行数是估算值,非精确;
  • 看字段注释用information_schema的COLUMN_COMMENT;
  • 修改结构前先SHOW CREATE TABLE留底;
  • 区分NULL和默认空串,Default列直接体现;
  • 自增字段在Extra列显示auto_increment。

总结

日常DESC快速看字段,要完整定义用SHOW CREATE TABLE,查索引用SHOW INDEX,看容量引擎用SHOW TABLE STATUS,脚本批量取元数据查information_schema。改结构前先把建表语句留底,避免误删索引或默认值。


emer 发布于  2026-10-19 07:34 

Linux查看CPU信息

Linux查看CPU信息

引言

服务器扩容、压测、排查性能瓶颈前,先要知道机器几颗CPU、多少核、主频和架构。/proc/cpuinfo是内核暴露的原生信息,配合lscpu、nproc能快速拿到规格,top/mpstat再看实时占用。

lscpu看汇总

lscpu

一次列出架构、颗数、每颗核数、线程数、主频、缓存,最简洁。

nproc看逻辑核数

nproc

直接输出可用逻辑CPU数,脚本里取核数最方便。

读/proc/cpuinfo

cat /proc/cpuinfo

每颗逻辑核一段,看model name型号、cpu MHz频率、flags指令集。

统计物理颗数和核数

# 物理CPU颗数
grep "physical id" /proc/cpuinfo | sort -u | wc -l
# 每颗物理核数
grep "cpu cores" /proc/cpuinfo | uniq
# 逻辑核总数
grep -c processor /proc/cpuinfo

物理颗数×每颗核数×超线程=逻辑核数。

实时CPU占用

top
mpstat 1

top看整体和进程,mpstat每秒采样看用户态、系统态、idle占比。

注意事项

  • 云主机看到的是分配的vCPU,不一定是物理独占;
  • 超线程逻辑核不等于物理性能翻倍;
  • flags里看是否支持虚拟化、AVX等指令集;
  • 排查高占用先top按P按CPU排序找进程;
  • 结合uptime看负载和核数是否匹配;
  • lscpu在大部分发行版预装,无此命令再读/proc。

总结

规格用lscpu看汇总、nproc取核数、/proc/cpuinfo读型号和指令集,配合grep统计物理颗数与核数,实时占用用top和mpstat。压测和扩容前先分清物理核、逻辑核和超线程,避免按vCPU误判真实算力。


emer 发布于  2026-10-19 07:32 

PHP判断数组为空

PHP判断数组为空

引言

接口返回、查询结果、表单收集都要先判断数组有没有数据,再决定走空分支还是遍历。empty、count、!$arr三种写法结果接近,但适用边界不同,选错会把0或null误判。

empty最常用

$list = [];
if (empty($list)) {
    echo '数组为空';
}

empty对空数组、未定义变量、null、0、''都返回true,不会报未定义警告,最适合先判空。

count取元素个数

if (count($arr) === 0) {
    echo '没有元素';
}

精确判断元素数量,count为0才是空;注意$arr本身未定义会警告,先isset。

逻辑非写法

if (!$arr) {
    echo '空';
}

短但要求$arr一定是已初始化数组,未定义会Notice。

判断键是否为空

不是判断整体,而是某键值:

if (empty($arr['name'])) {
    echo 'name为空';
}

避免直接取未定义键。

多维数组判空

if (!empty($arr['items']) && is_array($arr['items'])) {
    foreach ($arr['items'] as $item) {}
}

先确认外层键存在且是数组,再遍历内层。

注意事项

  • empty(0)和empty('')也为true,数字0场景别用empty判数组元素;
  • count第二个参数1可统计多维总元素;
  • 严格比较用count($arr)===0;
  • 数组里全是空字符串不等于空数组;
  • 查询无结果返回[]而非null,按空数组处理;
  • 结合isset防止未定义键警告。

总结

整体判空首选empty($arr)防未定义,精确统计用count($arr)===0,短逻辑非要求变量已初始化,判单个键用empty($arr['key']),多维先确认键存在再遍历。注意empty对0和空串也为真,数字场景改用count严格判断。


emer 发布于  2026-10-19 07:31 

Docker查看本地镜像

Docker查看本地镜像

引言

用Docker跑服务前先确认本地有哪些镜像、大小多少、标签是什么,避免重复拉取或用错版本。docker images系列命令能列出镜像仓库名、标签、ID、大小和创建时间。

列出全部本地镜像

docker images
# 等价
docker image ls

输出REPOSITORY、TAG、IMAGE ID、CREATED、SIZE五列。

只看镜像ID

docker images -q

只输出短ID,配合批量删除使用。

按名称过滤

docker images nginx
docker images | grep php

列出指定仓库名或关键词的镜像。

查看镜像详细信息

docker inspect nginx:latest

JSON输出架构、环境变量、挂载点、默认启动命令等。

查看镜像历史层

docker history nginx:latest

看每层做了什么改动、每层大小,理解镜像分层结构。

过滤和格式化

docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}"

自定义输出列,脚本里取数更方便。

注意事项

  • 同一个镜像不同TAG可能共用层,SIZE不重复累加;
  • 悬空镜像是旧版本残留,用prune清理;
  • 镜像大小是解压后占用,下载压缩包更小;
  • 看磁盘占用用docker system df;
  • 未被任何容器引用的镜像可安全删除;
  • 拉取前先docker images判断是否已存在。

总结

docker images列出本地镜像,-q取ID、按仓库名过滤、inspect看详情、history看分层、--format自定义输出。日常先列镜像确认版本和大小,再决定拉取或删除,配合system df掌握磁盘占用。


emer 发布于  2026-10-19 07:30 

Nginx代理缓存配置

Nginx代理缓存配置

引言

反向代理每次都回源取页面,后端压力大、首屏慢。Nginx自带proxy_cache,把后端响应存到本地磁盘,命中时直接返回,既减轻源站又加快响应,适合静态资源和不常变的页面。

定义缓存区

http块里先声明缓存目录和大小:

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m max_size=1g inactive=7d;
  • keys_zone=mycache:10m 是缓存名和索引内存;
  • max_size=1g 磁盘上限;
  • inactive=7d 7天没访问自动清理。

代理站点启用缓存

server或location块:

location / {
    proxy_cache mycache;
    proxy_cache_key $host$uri$is_args$args;
    proxy_cache_valid 200 304 1h;
    proxy_cache_valid 404 1m;
    proxy_cache_methods GET HEAD;
    proxy_pass http://backend;
}

200/304缓存1小时,404只存1分钟。

命中状态标识

加响应头方便排查:

add_header X-Cache-Status $upstream_cache_status;

HIT命中、MISS未命中、EXPIRED过期、BYPASS绕过。

绕过缓存的场景

登录后动态内容不缓存:

proxy_no_cache $http_cookie;
proxy_cache_bypass $http_cookie;

带cookie时不读不写缓存。

主动清除缓存

# 配置删除接口需要第三方模块或手动删目录
rm -rf /data/nginx/cache/*

更新内容后清对应目录,或按URL前缀匹配删除。

注意事项

  • 缓存目录要先mkdir并给nginx读写权限;
  • 带POST的接口不要缓存;
  • 频繁变动的页面缓存时间设短或不缓存;
  • 缓存键要带参数,避免不同query串内容;
  • 配置改完nginx -t校验再reload;
  • 大文件下载用分片缓存更稳妥。

总结

proxy_cache_path在http块定义缓存区,location里proxy_cache启用、proxy_cache_valid设有效期、proxy_cache_key拼缓存键,用X-Cache-Status看命中。静态和低频页面开缓存扛压力,动态登录内容用cookie绕过,更新后及时清理。


emer 发布于  2026-10-19 07:29 

MySQL唯一索引创建

MySQL唯一索引创建

引言

邮箱、手机号、订单号这类业务字段要求不能重复,光靠应用层判断并发下仍可能插入重复值。唯一索引在数据库层直接约束重复,是防脏数据的最后一道保险,同时还能加速等值查询。

建表时定义唯一索引

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    UNIQUE KEY uk_email (email)
);

uk_email是索引名,email列唯一。

已有表追加唯一索引

ALTER TABLE users ADD UNIQUE KEY uk_phone (phone);

数据里已有重复值时会报错1062,需先清理重复再加。

组合唯一索引

多列组合唯一,比如同一商品同一活动只领一次券:

ALTER TABLE coupon ADD UNIQUE KEY uk_user_goods (user_id, goods_id);

允许单列重复,但组合起来不能重复。

插入重复的报错处理

INSERT INTO users(email) VALUES('a@x.com');
-- 再次插入同email触发 1062 Duplicate entry

应用层catch错误码,返回邮箱已注册,而不是让500报错。

插入或更新冲突

INSERT INTO users(email) VALUES('a@x.com')
ON DUPLICATE KEY UPDATE login_time=NOW();

唯一键冲突时转成更新,适合登录时间刷新。

注意事项

  • 加唯一索引前先查重:SELECT email,COUNT(*) FROM users GROUP BY email HAVING COUNT(*)>1;
  • NULL在唯一索引里可以出现多个,MySQL不认为NULL相等;
  • 唯一索引也是普通索引,等值查询能走索引;
  • 大表加索引会锁表或耗时,高峰期用在线DDL;
  • 删除索引DROP INDEX uk_email ON users。

总结

唯一索引在建表时用UNIQUE KEY定义,已有表用ALTER TABLE ADD UNIQUE KEY追加,多列组合唯一用组合索引。加之前先清重复,插入冲突用ON DUPLICATE KEY UPDATE转更新,数据库层约束比应用层判断更可靠。


emer 发布于  2026-10-19 07:28 

PHP遍历关联数组

PHP遍历关联数组

引言

关联数组用键名而非数字下标组织数据,配置项、接口返回的JSON转成数组后都是关联数组。遍历要同时拿到键和值,foreach是最常用的方式,不同场景配合array_keys、array_walk更灵活。

foreach取键和值

$user = ['name'=>'刘馨怡','age'=>26,'city'=>'连云港'];
foreach ($user as $key => $value) {
    echo "$key: $value\n";
}

$key => $value同时拿到键名和值,最通用。

只取值

foreach ($user as $value) {
    echo $value;
}

不需要键名时省略$key。

用键名取单个值

echo $user['name'];
// 判断键是否存在
if (isset($user['email'])) {
    echo $user['email'];
}

取单值直接下标访问,先isset避免未定义键报错。

array_keys取所有键

$keys = array_keys($user);
print_r($keys); // ['name','age','city']

需要单独处理键名列表时用。

array_walk回调遍历

array_walk($user, function($value, $key) {
    echo "$key => $value";
});

适合把遍历逻辑封装成回调。

二维关联数组遍历

$list = [
    ['id'=>1,'name'=>'A'],
    ['id'=>2,'name'=>'B']
];
foreach ($list as $row) {
    echo $row['id'].'-'.$row['name'];
}

循环里再按键名取子元素。

注意事项

  • foreach不会改变原数组指针,比each安全;
  • 遍历中不要随意增删键,可能导致迭代异常;
  • 关联数组键名大小写敏感;
  • 值可能为null时用array_key_exists判断键是否存在,isset对null返回false;
  • 大数组遍历时注意内存,避免在循环内重复计算。

总结

关联数组遍历首选foreach的$key => $value形式,单值直接下标加isset判断,取键名用array_keys,封装逻辑用array_walk,二维数组外层foreach内层按键取值。掌握这几种就能应对配置、接口数据等绝大多数场景。


emer 发布于  2026-10-19 07:27 

Git查看提交历史

Git查看提交历史

引言

排查线上问题要追溯某行代码是谁、什么时候改的,就靠git log。学会用筛选和格式化参数,能快速定位某次提交,而不是在整屏历史里翻找。

基础查看

git log

默认从新到旧列出提交哈希、作者、时间、说明,按q退出。

一行精简显示

git log --oneline

每个提交压缩成一行短哈希加标题,浏览全貌最常用。

按作者和时间筛选

git log --author="张三"
git log --since="2026-10-01" --until="2026-10-10"
git log --grep="修复登录"

分别按作者、时间段、提交说明关键词过滤。

查看文件改动历史

git log --oneline -- index.php

只看某个文件的提交记录,追溯单个文件演变。

显示每次改动内容

git log -p
git log --stat

-p展开具体diff,--stat只看增删文件和行数概览。

图形化分支历史

git log --oneline --graph --all

用线条画出分支合并拓扑,理清多分支走向。

注意事项

  • --oneline配合--graph看分支最直观;
  • grep匹配提交说明,搜代码内容用git log -S或git blame;
  • 限制数量git log -n 10只看最近10条;
  • 已推送的公开历史不要用rebase改写;
  • 配合git show 哈希看单次提交详情。

总结

git log是追溯代码的主入口,--oneline精简、--author和--grep筛选、--graph看分支、-p看diff。排查问题时先按作者或关键词缩小范围,再用git show定位单次提交,比整屏翻找高效得多。


emer 发布于  2026-10-19 07:26 

Linux查看端口占用

Linux查看端口占用

引言

启动服务时报Address already in use,说明目标端口被别的进程占着。上线前要确认端口是否监听、被哪个PID占用,常用ss、netstat、lsof三个工具,先定位进程再决定停掉还是换端口。

ss查看(推荐)

ss替代netstat,更快更全:

ss -tlnp | grep 80
  • -t TCP,-l 监听状态,-n 数字端口不解析,-p 显示进程PID和名称。
    看TCP监听端口最直接。

netstat兼容命令

老系统没有ss时:

netstat -tlnp | grep 80

参数含义和ss一致,输出本地地址:端口、PID/程序名。

lsof按端口查进程

lsof -i:80

直接列出占用80端口的进程命令、PID、用户,适合只盯单个端口。

找到并处理

确认是无用进程后:

kill -9 PID

若是被系统服务占用,优先systemctl stop对应服务,别盲目kill。

查看所有监听端口

ss -tlnp

不加grep,列出全部TCP监听,盘点机器开了哪些服务。

注意事项

  • 查端口要root或sudo,普通用户看不到别的进程PID;
  • 状态LISTEN才是监听,ESTABLISHED是已建立连接,别混淆;
  • 端口被占先判断是不是正常服务,误杀线上进程影响业务;
  • 云服务器端口不通还要查安全组和防火墙,不只是本机占用;
  • ss在新发行版预装,netstat需装net-tools。

总结

日常用ss -tlnp grep端口最省事,netstat兼容老系统,lsof -i:端口看单个占用。定位PID后先确认进程归属再kill,端口连不上时本机占用、防火墙、云安全组三层都要排查。


emer 发布于  2026-10-19 07:25 

MySQL枚举与集合

MySQL枚举与集合

引言

状态、性别、标签这类取值固定的字段,有人用varchar存中文,导致拼写不一、无法约束。MySQL提供ENUM单选和SET多选两个字符串型,把合法值列在定义里,从源头限制脏数据。

ENUM单选

一个字段只能取定义值中的一个,适合性别、订单状态:

CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('待付款','已付款','已发货','已完成','已取消') NOT NULL DEFAULT '待付款'
);

插入不在列表的值,严格模式直接报错,非严格模式存空串,避免写错状态。

SET多选

一个字段可存多个定义值,适合兴趣、标签、权限位:

CREATE TABLE users (
    id INT PRIMARY KEY,
    interest SET('阅读','运动','音乐','旅行') NOT NULL
);
-- 插入多个值,逗号分隔
INSERT INTO users(interest) VALUES('阅读,音乐');

底层按位存储,最多64个成员。

两者区别

  • ENUM单选,SET多选;
  • ENUM内部按序号1、2、3存储,SET按二进制位;
  • ENUM常见于状态机,SET常见于标签和多选权限;
  • SET查单个值用FIND_IN_SET:
    SELECT * FROM users WHERE FIND_IN_SET('阅读', interest);

注意事项

  • 新增/修改枚举值要ALTER TABLE,字段多、值不稳定就别用ENUM;
  • 枚举值排序按内部序号而非字面字母序,容易误判;
  • 中文枚举注意字符集一致;
  • 关系型设计里多值标签更推荐关联表,SET只适合简单固定多选;
  • 不要用ENUM存会频繁增长的分类。

总结

ENUM单选约束状态,SET多选存标签,底层分别用序号和位存储。取值固定且变动少的字段用它们防脏数据,值频繁增加或需要多对多关系时改用独立关联表更规范。


emer 发布于  2026-10-19 07:24 
'); })();