Linux 命令速查表 — 按任务分类的 200 多条命令

按任务分类的 Linux 命令,从文件和权限到网络、systemd 和文本处理。每条都附常用参数、可复制的示例和 macOS 差异说明。

Linux 命令速查表 · freetoolsforweb.com/tools/linux-commands-cheat-sheet · 核对于 2026-10-18

最后核对:2026-10-18,依据 GNU coreutils 9.x、util-linux、procps-ng、iproute2、systemd 和 bash 5.2 手册;macOS 说明依据 macOS 26 的 man 手册页。

共 15 个分类,215 条

查看与编辑文本

读取文件、翻阅日志、在终端中编辑并比较不同版本。

cat

输出或合并文件

Linux · macOS#
cat [-n] [-A] file...
-n
给所有行编号
-A
把制表符显示为 ^I、行尾显示为 $(GNU);可发现 CRLF 换行符
cat /etc/os-release

输出文件内容

cat part1.txt part2.txt > whole.txt

拼接文件

cat -A script.sh | head

找出隐藏的制表符和 Windows 的 ^M 换行符

macOS/BSD: macOS 的 cat 没有 -A;用 cat -vet 可得到相同的显示效果。

tac

倒序输出文件,最后一行在前

Linux#
tac file
tac access.log | head

最新的日志行在前

macOS/BSD: macOS 没有此命令;请用 tail -r file。

less

分页浏览长文件或长输出

Linux · macOS#
less [-N] [-S] [+F] file
Space / b
向下 / 向上翻页
/text
向前搜索;n 下一个,N 上一个
g / G
跳到开头 / 结尾
F
像 tail -f 一样跟踪文件;按 Ctrl+C 停止
q
退出
-N
显示行号
-S
不自动换行(左右滚动查看)
less /var/log/syslog

阅读日志

journalctl -u nginx | less -S

长行不换行显示

head

显示文件的前几行

Linux · macOS#
head [-n N] [-c N] file...
-n N
前 N 行(默认 10 行)
-c N
前 N 个字节
-n -N
除最后 N 行外的全部内容(GNU)
head -n 20 data.csv

表头和前几行数据

head -c 512 file.bin | xxd

查看二进制文件的开头

macOS/BSD: macOS 的 head 不接受负数。

tail

显示文件末尾,或实时跟踪

Linux · macOS#
tail [-n N] [-f|-F] file...
-n N
最后 N 行(默认 10 行)
-n +N
从第 N 行开始
-f
随文件增长持续输出
-F
按文件名跟踪,日志轮转后依然有效
tail -n 50 app.log

最后 50 行

tail -F /var/log/nginx/access.log

跟踪会被轮转的日志

tail -n +2 data.csv

跳过 CSV 的表头行

nano

用简单的编辑器编辑文件

Linux#
nano file
Ctrl+O
保存
Ctrl+X
退出
Ctrl+W
搜索
Ctrl+K / Ctrl+U
剪切行 / 粘贴
Alt+U
撤销
sudo nano /etc/hosts

编辑系统文件

屏幕底部的快捷键栏会列出按键;^ 表示 Ctrl,M- 表示 Alt。

vim

用 vim 编辑文件(以及如何退出)

Linux · macOS#
vim file
i
插入模式(输入文本)
Esc
回到普通模式
:w / :q / :wq
保存 / 退出 / 保存并退出
:q!
不保存直接退出
/text
搜索;按 n 跳到下一个
dd / yy / p
删除行 / 复制行 / 粘贴
u / Ctrl+R
撤销 / 重做
vim +42 app.py

打开并定位到第 42 行

diff

比较两个文件或目录

Linux · macOS#
diff [-u] [-r] [-q] [-w] a b
-u
统一格式(patch 和 git 使用的格式)
-r
递归比较目录
-q
只报告文件是否不同
-w
忽略所有空白
-y
并排显示
diff -u old.conf new.conf

易读的改动视图

diff -rq dir1/ dir2/

两个目录树之间哪些文件不同

diff <(sort a.txt) <(sort b.txt)

排序后再比较,借助进程替换

tee

同时把输出写入文件和屏幕

Linux · macOS#
tee [-a] file...
-a
追加而不是覆盖
make 2>&1 | tee build.log

观看构建过程并保留日志

echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

追加到属于 root 的文件(sudo echo >> 会失败,因为重定向由 shell 执行)

printf

可靠地输出格式化文本

Linux · macOS#
printf 'format' args...
printf '%s\n' "$var"

安全地输出变量,即使它以 -n 开头

printf '%-12s %6.2f\n' disk 93.5

对齐的列

不同 shell 中 echo -e 和 echo -n 的行为不一致;printf 在哪里都一样。

column

把输出对齐成表格

Linux · macOS#
column -t [-s separators]
column -t -s, data.csv | less -S

把简单的 CSV 当表格阅读

mount | column -t

对齐以空白分隔的输出

xxd / hexdump

以十六进制查看文件

Linux · macOS#
xxd file | hexdump -C file
xxd image.png | head

十六进制与 ASCII 并排显示

hexdump -C file.bin | head

标准格式的十六进制转储

xxd 属于 vim 软件包;hexdump 在 util-linux 中(较新的 Debian/Ubuntu 上在 bsdextrautils 中)。

strings

从二进制文件中提取可读文本

Linux · macOS#
strings [-n min] file
-n N
只显示至少 N 个字符长的字符串(默认 4)
strings -n 8 firmware.bin | less

查找版本字符串、URL 和路径

在 Linux 上属于 binutils。

权限与所有权

查看和修改谁可以读取、写入和执行文件。

ls -l

看懂 -rwxr-x--- 这样的权限字符串

Linux · macOS#
ls -l file
ls -l deploy.sh

-rwxr-x--- 1 alice devs 812 Oct 18 09:12 deploy.sh

第一个字符表示类型(- 文件,d 目录,l 符号链接)。接下来是三组三位:所有者、所属组、其他所有人。r=4、w=2、x=1,所以 rwxr-x--- 就是 750。

chmod

用八进制数字修改权限

Linux · macOS#
chmod [-R] mode file...
-R
作用于目录及其中的所有内容
-v
报告每一处修改
chmod 644 index.html

所有者可读写,其他人只读:普通文件

chmod 755 deploy.sh

所有者全部权限,其他人可读可执行:脚本和目录

chmod 600 ~/.ssh/id_ed25519

私钥仅自己可读;权限过宽时 ssh 会拒绝使用

chmod u+x

用字母修改权限(u/g/o +/-)

Linux · macOS#
chmod [ugoa][+-=][rwxX] file...
chmod +x script.sh

让脚本可执行

chmod go-w file

去掉所属组和其他人的写权限

chmod -R u=rwX,go=rX site/

大写 X 只给目录和本来就有执行权限的文件设置执行权限

chmod -R 777

为什么 chmod -R 777 是错误的修复方式

危险Linux · macOS#
chmod -R 777 dir
find site/ -type d -exec chmod 755 {} +

正确的修复,第 1 步:目录设为 755

find site/ -type f -exec chmod 644 {} +

第 2 步:文件设为 644

危险: 这会让机器上的每个用户、每个被攻破的服务都能写入整个目录树,把所有文件标记为可执行,而且 ~/.ssh 为 777 时 OpenSSH 会拒绝使用其中的密钥。如果用在 /etc 或 /usr 上,可能会弄坏 sudo 乃至整个系统。请改用 chown 修正所有权,或者使用下面两条 find 命令。

chown

修改文件的所有者和所属组

危险Linux · macOS#
chown [-R] user[:group] file...
-R
递归
user:
末尾带冒号而不写组名时,同时把所属组设为该用户的登录组
sudo chown -R www-data:www-data /var/www/site

把网站根目录交给 Web 服务器用户

sudo chown "$USER": file.txt

接管 root 创建的文件

危险: 在 /、/usr 或 /etc 上执行 sudo chown -R 会清除 sudo、passwd 和各种服务所依赖的 setuid 位和所有权;恢复通常只能重装系统。请仔细核对路径。

chgrp

只修改文件的所属组

Linux · macOS#
chgrp [-R] group file...
chgrp -R developers /srv/shared

把共享文件夹交给团队组

umask

设置新文件的默认权限

Linux · macOS#
umask [mask]
umask

显示当前掩码,通常是 0022

umask 077

在当前 shell 中新文件为 600,新目录为 700

掩码用于去掉权限位:文件从 666 开始,目录从 777 开始,所以 022 得到 644 和 755。

sudo

以 root(或其他用户)身份运行命令

Linux · macOS#
sudo [-u user] [-i] command
-i
root 登录 shell
-u user
以该用户而不是 root 身份运行
-l
列出你被允许运行的命令
-k
清除缓存的凭据
sudo systemctl restart nginx

执行一条管理命令

sudo !!

用 sudo 重新运行上一条命令

sudo -u postgres psql

以服务用户身份运行

su

切换到其他用户

Linux · macOS#
su [-] [user]
su - deploy

以 deploy 身份登录并加载其环境

sudo su -

root 没有设置密码时获得 root shell(sudo -i 效果相同)

setfacl / getfacl

用 ACL 为额外的某个用户授权

Linux#
setfacl -m u:user:perms file
-m
修改(添加)条目
-x
删除条目
-b
删除所有 ACL 条目
-R
递归
-d
设置新文件继承的默认 ACL
setfacl -m u:alice:rw report.xlsx

alice 可读写,且不改变所属组

getfacl report.xlsx

显示所有条目

setfacl -R -m g:devs:rwX /srv/app

让某个组获得整个目录树的访问权限

ls -l 权限字符串末尾的 + 表示文件带有 ACL。

chattr / lsattr

让文件不可更改

Linux#
chattr +i|-i file
sudo chattr +i /etc/resolv.conf

在去掉 -i 之前,任何人(包括 root)都无法修改或删除它

lsattr /etc/resolv.conf

显示属性;i 表示不可更改

支持 ext4、XFS、Btrfs。如果即使是 root 也出现“Operation not permitted”,请检查 lsattr。

进程与作业

查看正在运行什么、停止它,以及在后台运行任务。

ps

列出正在运行的进程

Linux · macOS#
ps aux | ps -ef | ps -o fields -p PID
aux
所有进程,含 CPU、内存和用户(BSD 风格)
-ef
所有进程,含父进程 PID(System V 风格)
-o
选择要显示的列
--sort=-%mem
按内存排序,最高的在前(procps)
ps aux | grep [n]ginx

[n] 技巧可以把 grep 自身排除在结果之外

ps aux --sort=-%mem | head

占用内存最多的进程

ps -o pid,ppid,etime,cmd -p 1234

进程已经运行了多久

macOS/BSD: macOS 的 ps 没有 --sort;请用 ps aux -m(按内存)或 ps aux -r(按 CPU)。

pstree

以父子树形式显示进程

Linux#
pstree [-p] [user|PID]
pstree -p

带 PID

pstree -p 1234

某个进程派生了哪些子进程

top

实时查看 CPU 和内存使用情况

Linux · macOS#
top [-u user] [-p PID] [-b -n 1]
P / M
按 CPU / 内存排序(Linux top)
1
显示每个 CPU 核心
k
按 PID 结束进程
q
退出
-b -n 1
单次批处理快照,适合脚本
top -b -n 1 | head -20

可以直接贴进工单的快照

macOS/BSD: macOS 的 top 是另一个程序:用 top -o cpu 或 top -o mem 排序。

htop

更友好的交互式进程查看器

Linux#
htop [-u user]
F3 or /
搜索
F4
筛选
F6
选择排序列
F9
发送信号(kill)
t
树状视图
htop -u www-data

只看某个用户的进程

安装方法:apt install htop / dnf install htop。

pgrep

按名称查找进程 ID

Linux · macOS#
pgrep [-a] [-f] [-u user] pattern
-a
显示完整命令行(Linux procps)
-f
匹配完整命令行,而不仅是进程名
-u user
只看该用户的进程
-x
精确匹配名称
pgrep -a nginx

PID 和命令行

pgrep -f 'python manage.py runserver'

按参数匹配某个脚本

macOS/BSD: 在 macOS 上,-a 表示“包括祖先进程”;请用 pgrep -lf 查看名称和参数。

pkill

按名称停止进程

Linux · macOS#
pkill [-signal] [-f] [-u user] pattern
pkill -f "node server.js"

停止某个 Node 应用

pkill -HUP nginx

发送重新加载信号

pgrep -af node

结束进程前先预览 -f 会匹配到什么

模式是正则表达式,只要名称中任意位置匹配即可;pkill node 也会命中 nodejs-helper。请先用 pgrep 预览。

kill

向进程发送信号(停止、强制结束、重新加载)

Linux · macOS#
kill [-signal] PID...
(none) / -15 / -TERM
请进程正常退出(默认)
-9 / -KILL
强制结束;无法被捕获,不做清理
-1 / -HUP
许多守护进程会重新加载配置
-l
列出信号名称
kill 1234

礼貌地停止

kill -9 1234

TERM 被忽略时的最后手段

kill %1

结束当前 shell 的作业 1

先用普通的 kill 并等几秒:-9 会跳过清理,可能留下临时文件、锁和写了一半的数据。

killall

结束所有指定名称的进程

Linux · macOS#
killall [-signal] name
killall firefox

所有 Firefox 进程

在 Linux 上它属于 psmisc 软件包。

Ctrl+Z, bg, fg, jobs

暂停命令并在后台继续运行

Linux · macOS#
Ctrl+Z; bg [%n]; fg [%n]; jobs
jobs

列出当前 shell 中的作业及其编号

bg %1

在后台恢复作业 1

fg %1

把它调回前台

Ctrl+Z 会挂起前台程序(在执行 bg 或 fg 之前它会停止运行)。

&

在后台启动命令

Linux · macOS#
command &
./long-export.sh > export.log 2>&1 &

启动后立即返回提示符

wait

在脚本中等待后台作业完成

nohup

退出登录后让命令继续运行

Linux · macOS#
nohup command > log 2>&1 &
nohup ./server > server.log 2>&1 &

关闭 SSH 会话后依然运行

对于需要长期运行的程序,systemd 服务(见“服务与日志”)或 tmux 更可靠。

disown

把已在运行的作业与 shell 分离

Linux · macOS#
disown [-h] [%n]
disown -h %1

忘了用 nohup:先用 bg 放到后台,再 disown

tmux

断线后保持终端会话

Linux#
tmux new -s name | tmux attach -t name
Ctrl+B d
分离(会话继续运行)
Ctrl+B c
新建窗口
Ctrl+B % / Ctrl+B "
左右分屏 / 上下分屏
tmux ls
列出会话
tmux new -s deploy

新建一个命名会话

tmux attach -t deploy

SSH 断开后重新连接

用包管理器安装。GNU screen 是较老的替代品(Ctrl+A d 分离,screen -r 重新连接)。

nice / renice

以较低(或较高)的 CPU 优先级运行命令

Linux · macOS#
nice -n N command | renice -n N -p PID
nice -n 19 tar -czf backup.tgz /data

不影响其他任务的后台备份

sudo renice -n -5 -p 1234

提高正在运行的进程的优先级

nice 值范围是 -20(优先级最高)到 19(最低)。只有 root 能设为 0 以下。

timeout

命令运行太久时将其结束

Linux#
timeout [-s signal] duration command
timeout 30s curl -s https://example.com/health

30 秒后放弃

timeout -s KILL 5m ./job.sh

五分钟后强制结束

达到时间限制时以状态码 124 退出。

watch

每隔几秒重新运行命令

Linux#
watch [-n seconds] [-d] command
watch -n 2 df -h

观察磁盘空间被占满的过程

watch -d 'ss -s'

-d 会高亮显示变化的部分

lsof

查看哪个进程打开了某个文件或端口

Linux · macOS#
lsof [-i :port] [-p PID] [file]
sudo lsof -i :8080

谁在监听 8080 端口

sudo lsof +L1

仍被打开的已删除文件(磁盘已满但 du 显示不出来)

lsof -p 1234

某个进程打开的所有文件

fuser

查找(或结束)正在使用某个挂载点或端口的进程

危险Linux#
fuser [-v] [-m] [-k] target
sudo fuser -vm /mnt/usb

为什么 umount 提示“target is busy”

sudo fuser -v 8080/tcp

占用某个 TCP 端口的进程

危险: fuser -k 会不加提示地结束所有使用目标的进程;对挂载点使用时,其中可能包括你自己的 shell。

time

测量命令的运行时间

Linux · macOS#
time command
time ./build.sh

real = 实际耗时,user + sys = CPU 时间

strace

跟踪程序发出的系统调用

Linux#
strace [-f] [-e trace=...] command | strace -p PID
strace -f -e trace=openat ./app 2>&1 | grep -v ENOENT

它实际打开了哪些文件?

sudo strace -p 1234

卡住的进程在等什么?

系统信息与资源

操作系统版本、内核、CPU、内存、硬件、时间和负载。

uname

显示内核版本和架构

Linux · macOS#
uname [-a|-r|-m]
-a
全部信息
-r
内核版本号
-m
机器架构:x86_64、aarch64
uname -r

例如 6.8.0-45-generic

uname -m

该下载哪个版本的二进制文件:x86_64 还是 aarch64

cat /etc/os-release

查看 Linux 发行版及版本

Linux#
cat /etc/os-release
cat /etc/os-release

所有 systemd 时代发行版都有的 NAME、VERSION_ID、ID

lsb_release -a

Debian/Ubuntu 上的替代方法(如已安装)

macOS/BSD: macOS:sw_vers。

hostnamectl

显示或设置主机名

Linux#
hostnamectl [set-hostname name]
hostnamectl

主机名、操作系统、内核、虚拟化

sudo hostnamectl set-hostname web01

重命名这台机器

uptime

显示运行时间和平均负载

Linux · macOS#
uptime
uptime

过去 1、5、15 分钟的平均负载

负载是正在运行或等待运行的进程数。请与 CPU 数(nproc)对比:4 核机器负载为 4 表示已满负荷。

free

查看内存和交换空间使用情况

Linux#
free [-h]
free -h

看“available”列,而不是“free”列

macOS/BSD: macOS:vm_stat,或 top -l 1 | grep PhysMem。

Linux 会把空闲内存用作磁盘缓存,所以健康的机器上“free”看起来也很低。“available”才是程序还能用到的内存。

lscpu / nproc

显示 CPU 型号和核心数

Linux#
lscpu | nproc
lscpu

型号、插槽、核心、线程、特性标志

make -j"$(nproc)"

用上所有可用核心

macOS/BSD: macOS:sysctl -n hw.ncpu 和 sysctl -n machdep.cpu.brand_string。

lspci / lsusb

列出 PCI 和 USB 设备

Linux#
lspci [-k] | lsusb
lspci -k | grep -A3 -i vga

显卡及正在使用的驱动

lsusb

系统到底有没有识别到这个 USB 设备?

dmidecode / lshw

显示内存插槽、BIOS 和硬件详情

Linux#
sudo dmidecode -t type | sudo lshw -short
sudo dmidecode -t memory | grep -i size

每个插槽上安装的内存

sudo lshw -short

每个设备一行

dmesg

查看内核消息(硬件、驱动、OOM 结束进程)

Linux#
dmesg [-T] [-w] [--level=...]
-T
易读的时间戳
-w
跟踪新消息
--level=err,warn
只看问题
sudo dmesg -T | tail -30

刚刚发生了什么(插入 USB、磁盘错误)

sudo dmesg -T | grep -i 'out of memory'

是不是 OOM killer 结束了你的应用?

/proc

从 /proc 读取原始的 CPU、内存和进程信息

Linux#
cat /proc/<file>
grep MemAvailable /proc/meminfo

可用内存(单位 kB)

grep -c ^processor /proc/cpuinfo

逻辑 CPU 数量

cat /proc/1234/status

单个进程的状态和内存

vmstat / iostat

判断瓶颈在 CPU、内存还是磁盘

Linux#
vmstat interval count | iostat -xz interval
vmstat 1 5

r = 运行队列,si/so = 换页,wa = 等待 I/O

iostat -xz 1

每块磁盘的利用率(%util)和延迟(await)

iostat 来自 sysstat 软件包。

date

输出或计算日期和 Unix 时间戳

Linux · macOS#
date [+format] [-d 'description']
+%F
YYYY-MM-DD
+%s
Unix 时间戳(秒)
-d 'text'
解析日期:tomorrow、2 days ago、@1700000000(GNU)
-u
UTC
date '+%Y-%m-%d %H:%M:%S'

用于日志的时间戳

date +%s

自 1970-01-01 UTC 起的秒数

date -d @1700000000

时间戳转日期(GNU)

date -d '2 days ago' +%F

相对日期(GNU)

macOS/BSD: macOS 的 date 没有 -d。时间戳转日期用 date -r 1700000000,“2 天前”用 date -v-2d,解析日期用 date -j -f '%Y-%m-%d' 2026-10-18 +%s。

timedatectl

设置时区并检查时钟同步

Linux#
timedatectl [set-timezone Zone]
timedatectl

本地时间、UTC、时区,NTP 是否已同步?

timedatectl list-timezones | grep America

查找时区名称

sudo timedatectl set-timezone America/Toronto

修改时区

磁盘与文件系统

剩余空间、空间被谁占用、分区、挂载与格式化。

df

查看磁盘剩余空间

Linux · macOS#
df [-h] [-T] [-i] [path]
-h
易读的大小
-T
显示文件系统类型(GNU)
-i
显示 inode 使用量而不是字节数
df -h

所有已挂载的文件系统

df -h .

当前目录所在的文件系统

df -i

明明还有空闲字节却提示“No space left”?可能是 inode 用完了

macOS/BSD: 在 macOS 上,-T 是按类型筛选,而不是显示类型。

du

查找什么占用了磁盘空间

Linux · macOS#
du [-s] [-h] [-d depth] [path...]
-s
每个参数只显示一个总计
-h
易读格式
-d N
深度限制(GNU 长选项:--max-depth=N)
-x
不跨越文件系统
du -sh /var/log

单个文件夹的大小

du -h -d 1 | sort -h

各子文件夹大小,最大的排在最后(GNU 和 macOS 通用)

sudo du -xh -d 1 / | sort -h | tail

最大的几个顶层目录

macOS/BSD: macOS 的 du 有 -d,但没有 --max-depth。

ncdu

交互式浏览磁盘占用

Linux#
ncdu [-x] [path]
sudo ncdu -x /

用方向键浏览,按 d 删除

安装方法:apt install ncdu / dnf install ncdu。

lsblk

列出磁盘和分区

Linux#
lsblk [-f]
-f
文件系统类型、卷标、UUID、挂载点
lsblk

磁盘、分区、大小、挂载点

lsblk -f

哪个分区是 ext4/xfs,以及它的 UUID

macOS/BSD: macOS:diskutil list。

blkid

获取分区的 UUID

Linux#
sudo blkid [device]
sudo blkid /dev/sdb1

UUID 和 TYPE,用于 /etc/fstab

findmnt

显示什么挂载在哪里

Linux#
findmnt [target] | findmnt -T path
findmnt

挂载树及挂载选项

findmnt -T /var/lib/docker

这个路径位于哪个文件系统

sudo findmnt --verify

重启前检查 /etc/fstab 是否有错误

mount

挂载磁盘或分区

Linux#
mount [-t type] [-o options] device dir
sudo mount /dev/sdb1 /mnt/usb

挂载 U 盘(目录必须已存在)

sudo mount -o remount,rw /

把只读的根分区改为可写

sudo mount -t nfs nas:/export /mnt/nas

挂载 NFS 共享

umount

卸载磁盘

Linux#
umount dir|device
sudo umount /mnt/usb

执行后即可安全拔出

sudo umount -l /mnt/nas

延迟卸载:立即分离,不再占用时再清理

“target is busy”表示有进程(往往是停留在该目录中的你自己的 shell)正在使用它:用 fuser -vm 或 lsof 找出来。

/etc/fstab

开机时自动挂载磁盘

Linux#
UUID=<uuid> <mountpoint> <type> <options> <dump> <pass>
UUID=3f6c...  /data  ext4  defaults,nofail  0  2

每个文件系统一行;nofail 让磁盘缺失时也能继续开机

sudo mount -a

立即挂载 fstab 中的所有条目:重启前先测试

fstab 中的一个笔误就可能让下次开机进入紧急模式。编辑后务必运行 sudo mount -a(或 findmnt --verify)。

fdisk / parted

查看或编辑分区表

危险Linux#
sudo fdisk -l | sudo fdisk /dev/sdX | sudo parted /dev/sdX print
sudo fdisk -l

所有磁盘及其分区

sudo parted /dev/sdb print

分区表类型(gpt/msdos)和布局

危险: 写入分区表(fdisk 中的 w、parted 中的 mklabel)会让该磁盘上的现有数据无法访问。请先用 lsblk 确认设备名;/dev/sda 和 /dev/sdb 很容易对调。

mkfs

格式化分区

危险Linux#
sudo mkfs.<type> device
sudo mkfs.ext4 -L data /dev/sdb1

带卷标的 ext4

sudo mkfs.vfat -F 32 /dev/sdc1

FAT32 格式,让其他设备也能读取 U 盘

危险: 会立即擦除目标上的文件系统,如果设备未挂载则不会有任何确认。请用 lsblk -f 核对设备;把 /dev/sda1 错写成 /dev/sda,或者选错磁盘,都会毁掉整块磁盘的数据。

fsck

检查并修复文件系统

危险Linux#
sudo fsck [-f] device
sudo fsck -f /dev/sdb1

强制完整检查一个未挂载的分区

危险: 切勿对以读写方式挂载的文件系统运行 fsck:可能会损坏它。请先卸载;如果是根文件系统,请从救援介质启动。

dd

把 ISO 写入 U 盘或复制原始磁盘

危险Linux · macOS#
dd if=input of=output bs=size [status=progress] [conv=fsync]
if= / of=
输入 / 输出文件或设备
bs=4M
块大小;越大越快
status=progress
显示已复制的字节数(GNU)
conv=fsync
退出前把数据刷入设备
sudo dd if=ubuntu.iso of=/dev/sdX bs=4M status=progress conv=fsync

制作可启动 U 盘(把 sdX 换成整块磁盘,而不是分区)

dd if=/dev/zero of=test.img bs=1M count=100

创建一个 100 MB 的文件

危险: dd 会不加询问地覆盖 of= 指定的目标。把 if= 和 of= 写反,或者选错 /dev/sdX,都会抹掉那块磁盘。运行前用 lsblk 再确认一次。

macOS/BSD: macOS:先执行 diskutil unmountDisk,再以 /dev/rdiskN(来自 diskutil list)为目标,使用 bs=4m,按 Ctrl+T 查看进度。

sync

把待写入的数据刷入磁盘

Linux · macOS#
sync
sync && sudo umount /mnt/usb

拔出 U 盘之前

swapon / mkswap

查看或添加交换空间

Linux#
swapon --show | mkswap file && swapon file
swapon --show

当前的交换空间

sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile

添加 2 GB 交换文件(写入 /etc/fstab 才能永久生效)

在 Btrfs 上创建交换文件需要额外步骤(较新的 btrfs-progs 中使用 btrfs filesystem mkswapfile)。

shred

删除前先覆写文件

危险Linux#
shred [-u] [-n passes] file
shred -u -n 3 secrets.txt

覆写三次后删除

危险: 不可逆。另请注意,它在 SSD、日志型或写时复制文件系统(Btrfs、ZFS)以及任何带快照的存储上并不可靠;真正的保护请使用全盘加密。

网络

IP 地址、路由、开放端口、HTTP 请求、DNS、SSH 和文件传输。

ip addr

显示本机的 IP 地址

Linux#
ip [-br] addr [show dev IFACE]
ip -br a

每个网卡一行:名称、状态、地址

ip a show eth0

查看单个网卡的详细信息

hostname -I

只显示 IP 地址

macOS/BSD: macOS:ifconfig,或 ipconfig getifaddr en0。

ip 取代了旧的 ifconfig(net-tools),很多发行版已不再默认安装后者。

ip route

显示路由表和默认网关

Linux#
ip route [get ADDRESS] | ip route add NET via GW
ip r

路由;“default via”后面就是网关

ip route get 1.1.1.1

访问某个目标时使用哪个网卡和网关

sudo ip route add 10.20.0.0/16 via 192.168.1.1

添加路由(重启后失效)

ip link

启用或停用网卡

危险Linux#
ip link [set IFACE up|down]
ip link

网卡和 MAC 地址

sudo ip link set eth0 down && sudo ip link set eth0 up

重启某个网卡

危险: 停用你通过 SSH 连接所用的网卡会切断当前会话。

ss

列出监听端口和已打开的连接

Linux#
ss [-t] [-u] [-l] [-p] [-n]
-t / -u
TCP / UDP
-l
只看监听中的套接字
-p
显示进程(要查看其他用户的进程需加 sudo)
-n
端口显示为数字,不做 DNS 解析
-s
汇总统计
sudo ss -tulpn

所有监听端口及对应程序

ss -tn state established '( dport = :443 )'

到 443 端口的已建立连接

ss -s

连接总数

macOS/BSD: macOS:lsof -iTCP -sTCP:LISTEN -n -P,或 netstat -an。

ss 取代了 netstat;装有 net-tools 的系统上 netstat -tulpn 仍然可用。

curl

发送 HTTP 请求或下载文件

Linux · macOS#
curl [options] URL
-I
只看响应头(HEAD 请求)
-L
跟随重定向
-o file / -O
保存到文件 / 按远程文件名保存
-s / -S
静默 / 但仍显示错误
-f
遇到 HTTP 4xx/5xx 时失败退出(退出码 22),而不是输出错误页面
-v
详细模式:请求和响应头、TLS
curl -I https://example.com

状态行和响应头

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

下载文件,并跟随重定向

curl -s -o /dev/null -w '%{http_code}\n' https://example.com

只看状态码

curl -fsSL https://example.com/install.sh -o install.sh

先下载脚本,看过再运行

curl -d

发送带 JSON 的 POST 请求

Linux · macOS#
curl -H 'Content-Type: application/json' -d 'json' URL
-d data
请求体;自动使用 POST
--data-binary @file
原样发送文件
-H header
添加请求头
-X METHOD
PUT、PATCH、DELETE…
-u user:pass
基本认证
curl -H 'Content-Type: application/json' -d '{"name":"Ada"}' https://api.example.com/users

POST JSON

curl -H "Authorization: Bearer $TOKEN" https://api.example.com/me

使用双引号,$TOKEN 才会被展开

curl -X DELETE https://api.example.com/users/42

其他请求方法

wget

下载文件(支持断点续传)

Linux#
wget [options] URL
-c
继续未完成的下载
-O file
另存为(用 -O- 输出到标准输出)
-q
静默模式
-r -np
递归下载,绝不上溯到父目录
wget -c https://example.com/big.iso

断线后继续下载

wget -qO- https://example.com/data.json | jq .

直接通过管道交给另一个命令

macOS/BSD: macOS 默认没有;请用 curl -LO(续传用 curl -C - -LO)。

dig

查询 DNS 记录

Linux · macOS#
dig [@server] name [type] [+short]
dig +short example.com

只看 A 记录

dig MX example.com

邮件服务器

dig @1.1.1.1 example.com

向指定的解析服务器查询(绕过本地缓存)

dig -x 8.8.8.8

反向解析

dig +trace example.com

从根服务器开始跟踪委派过程

软件包名:dnsutils(Debian/Ubuntu)或 bind-utils(Fedora/RHEL)。

host / nslookup

快速查询 DNS

Linux · macOS#
host name | nslookup name [server]
host example.com

一个简短回答中包含 A、AAAA 和 MX

nslookup example.com 8.8.8.8

Windows 上也有同样的命令

resolvectl

查看正在使用的 DNS 服务器并清除 DNS 缓存

Linux#
resolvectl [status|query|flush-caches]
resolvectl status

各网卡的 DNS 服务器

sudo resolvectl flush-caches

清除 systemd-resolved 缓存

macOS/BSD: macOS:sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder。

仅适用于使用 systemd-resolved 的系统(Ubuntu、Fedora 默认使用)。

ping

测试主机是否可达

Linux · macOS#
ping [-c count] [-i interval] host
-c N
发送 N 个数据包后停止
-i sec
数据包之间的间隔
-4 / -6
强制使用 IPv4 / IPv6
ping -c 4 example.com

发送四个数据包,然后显示汇总

在 Linux 和 macOS 上,除非加 -c,ping 会一直运行到按下 Ctrl+C 为止(Windows 发送 4 次后停止)。没有回应并不一定代表主机宕机:很多主机会屏蔽 ICMP。

traceroute / tracepath

查看数据包到达主机所经过的路由

Linux · macOS#
traceroute [-n] host | tracepath host
traceroute -n example.com

显示各跳,不做 DNS 解析

tracepath example.com

无需 root,还会报告 MTU

macOS/BSD: macOS 有 traceroute,但没有 tracepath。

Linux 上可能需要另行安装 traceroute;tracepath(iputils)通常已自带。

mtr

找出在哪里发生丢包

Linux#
mtr [-r] [-w] [-c count] host
mtr -rw -c 100 example.com

每跳探测 100 次后输出报告

结合了 ping 和 traceroute。如果只有中间某一跳丢包,通常是该路由器降低了 ICMP 的优先级;一直持续到终点的丢包才是真正的丢包。

ssh

登录远程机器

Linux · macOS#
ssh [-p port] [-i key] [-J jump] user@host [command]
ssh alice@203.0.113.10

登录

ssh -p 2222 alice@host

非标准端口

ssh alice@host 'df -h'

执行一条命令后返回

ssh -J bastion.example.com alice@10.0.0.5

通过跳板机中转

ssh -L / -R / -D

通过 SSH 转发端口(隧道)

Linux · macOS#
ssh -L local:host:remote user@server
-L 5432:localhost:5432
本地 5432 端口连到服务器上的 5432 端口
-R 8080:localhost:3000
服务器的 8080 端口连到你本地的 3000 端口
-D 1080
在本地 1080 端口开启 SOCKS 代理
-N
不执行远程命令,只建立隧道
ssh -N -L 5432:localhost:5432 alice@db-host

用本地数据库客户端连接远程 Postgres

ssh -N -D 1080 alice@host

通过服务器上网浏览

ssh-keygen

创建 SSH 密钥并安装到服务器

Linux · macOS#
ssh-keygen -t ed25519 [-C comment] | ssh-copy-id user@host
ssh-keygen -t ed25519 -C "you@example.com"

在 ~/.ssh 中生成新的密钥对

ssh-copy-id alice@host

把你的公钥追加到服务器的 authorized_keys

ssh-keygen -R host

服务器重装后删除旧的主机密钥(“REMOTE HOST IDENTIFICATION HAS CHANGED”)

~/.ssh/config

把 SSH 连接设置保存为简短别名

Linux · macOS#
Host alias / HostName / User / Port / IdentityFile
Host web
  HostName 203.0.113.10
  User deploy
  Port 2222
  IdentityFile ~/.ssh/id_ed25519

之后只需:ssh web(scp 和 rsync 也会使用它)

scp

通过 SSH 与服务器互传文件

Linux · macOS#
scp [-r] [-P port] source... dest
-r
复制目录
-P port
端口(大写 P;ssh 用的是小写 -p)
-i key
身份密钥文件
scp report.pdf alice@host:/tmp/

上传

scp alice@host:/var/log/app.log .

下载

scp -r -P 2222 site/ alice@host:~/

通过其他端口上传文件夹

自 OpenSSH 9.0 起,scp 底层改用 SFTP 协议。大量或重复复制时 rsync 更快,因为它只传输变化的部分。

rsync

在本地或通过 SSH 同步文件夹

Linux · macOS#
rsync [-avz] [--progress] [-n] source dest
-a
归档模式:递归,保留权限、时间和链接
-v
详细输出
-z
传输时压缩
-P
显示进度,并支持续传未完成的文件
-n
演练模式:只显示将会发生什么
--exclude 'pattern'
跳过文件
-e 'ssh -p 2222'
自定义 SSH 选项
rsync -avzP site/ deploy@host:/srv/site/

site/ 末尾的斜杠表示复制其内容,而不是文件夹本身

rsync -av --exclude 'node_modules' ./ /backup/app/

本地备份,排除无用文件

macOS/BSD: 较新的 macOS 自带 openrsync 而不是 rsync;常用选项可用,部分少见选项不支持。

src/ 表示“src 中的内容”;不带斜杠的 src 表示“src 这个文件夹”。弄错的话会多套一层文件夹(dest/src/…)。

rsync --delete

让目标成为源的精确镜像

危险Linux · macOS#
rsync -av --delete source/ dest/
rsync -avn --delete site/ /srv/site/

先演练:以“deleting”开头的行就是会被删除的内容

rsync -av --delete site/ /srv/site/

然后正式运行

危险: 会删除 dest 中所有 source 里没有的内容。把源和目标写反,或者源路径为空或写错,都会清空目标。务必先加 -n 运行一次。

nc

测试 TCP 端口是否开放

Linux · macOS#
nc -zv host port | nc -l port
nc -zv db.internal 5432

结果为“succeeded”,或“Connection refused”/超时

nc -l 9000

在端口上监听,从另一端测试防火墙

不同版本的 netcat 选项不同:传统版本需要写成 nc -l -p 9000。

ufw

在 Ubuntu 上管理防火墙

危险Linux#
sudo ufw [status|allow|deny|delete|enable]
sudo ufw status verbose

规则和默认策略

sudo ufw allow 22/tcp

放行 SSH(在 enable 之前执行)

sudo ufw allow from 10.0.0.0/8 to any port 5432

只对一个网段开放一个端口

危险: 在远程服务器上,如果没有先放行 SSH(ufw allow OpenSSH 或 22/tcp)就执行 sudo ufw enable,你会把自己锁在外面。

firewall-cmd

在 Fedora/RHEL 上管理防火墙

Linux#
sudo firewall-cmd [--permanent] --add-service|--add-port ...
sudo firewall-cmd --list-all

当前区域和规则

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

永久开放 HTTPS

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

开放端口

不加 --permanent 的规则只在下次重新加载或重启前有效。

nmcli

管理 Wi-Fi 和网络连接(NetworkManager)

Linux#
nmcli [device|connection] ...
nmcli device status

网卡及其连接状态

nmcli device wifi list

附近的网络

nmcli device wifi connect 'MyWiFi' password 'secret'

连接到网络

软件包管理:apt、dnf、pacman、zypper

同一任务在四大包管理器中的写法:Debian/Ubuntu(apt)、Fedora/RHEL(dnf)、Arch(pacman)、openSUSE(zypper)。凡是会改动系统的操作,请在前面加上 sudo。

任务apt(Debian、Ubuntu)dnf(Fedora、RHEL)pacman(Arch)zypper(openSUSE)
刷新软件包列表 #
元数据过期时 dnf 会自动刷新。在 Arch 上,切勿先运行 pacman -Sy 再运行 -S pkg:官方不支持部分升级,请使用 -Syu。
apt update
dnf makecache
pacman -Sy
zypper refresh
升级所有软件包 #
openSUSE Tumbleweed 使用 zypper dup。apt full-upgrade 在必要时还会删除软件包以完成升级。
apt update && apt upgrade
dnf upgrade
pacman -Syu
zypper update
安装软件包 #
apt install nginx
dnf install nginx
pacman -S nginx
zypper install nginx
安装下载好的软件包文件 #
./ 告诉 apt 这是一个文件而不是包名,这样依赖会被自动解决(dpkg -i 不会)。
apt install ./app.deb
dnf install ./app.rpm
pacman -U app.pkg.tar.zst
zypper install ./app.rpm
卸载软件包 #
apt remove nginx
dnf remove nginx
pacman -R nginx
zypper remove nginx
卸载并删除配置文件 / 无用依赖 #
apt purge nginx && apt autoremove
dnf remove nginx && dnf autoremove
pacman -Rns nginx
zypper remove --clean-deps nginx
查看软件包详情 #
apt show nginx
dnf info nginx
pacman -Si nginx (installed: -Qi)
zypper info nginx
列出已安装的软件包 #
apt list --installed
dnf list --installed
pacman -Q
zypper search --installed-only
列出可用更新 #
apt list --upgradable
dnf check-update
checkupdates (pacman-contrib)
zypper list-updates
查询文件属于哪个软件包 #
对于尚未安装的文件:dnf provides /path、apt-file search path(需要安装 apt-file)、pacman -F path。
dpkg -S /usr/bin/curl
rpm -qf /usr/bin/curl
pacman -Qo /usr/bin/curl
rpm -qf /usr/bin/curl
列出软件包安装的文件 #
dpkg -L nginx
rpm -ql nginx
pacman -Ql nginx
rpm -ql nginx
锁定软件包的当前版本 #
在 DNF 4 上,versionlock 需要安装 versionlock 插件包。
apt-mark hold nginx
dnf versionlock add nginx
IgnorePkg = nginx in /etc/pacman.conf
zypper addlock nginx
清理软件包缓存 #
apt clean
dnf clean all
pacman -Sc
zypper clean

用户与用户组

你是谁、谁已登录,以及账户管理。

whoami / id

显示你的用户名、UID 和所属组

Linux · macOS#
whoami | id [user]
id

uid、gid 以及你所属的每个组

id alice

其他用户

who / w / last

查看谁已登录以及最近的登录记录

Linux · macOS#
who | w | last [-n N]
w

谁在线以及正在运行什么

last -n 10

最近的登录和重启记录

sudo lastb -n 10

最近的登录失败记录(Linux)

useradd

创建用户账户

Linux#
sudo useradd [-m] [-s shell] [-G groups] user
-m
创建主目录(并非所有发行版都默认创建)
-s /bin/bash
登录 shell
-G group1,group2
附加组
sudo useradd -m -s /bin/bash alice && sudo passwd alice

创建用户并设置密码

在 Debian/Ubuntu 上,adduser alice 是更友好的交互式封装,会设置好主目录和密码。

usermod -aG

把用户加入用户组

危险Linux#
sudo usermod -aG group user
sudo usermod -aG docker alice

让 alice 可以运行 docker

sudo usermod -aG sudo alice

在 Debian/Ubuntu 上授予管理员权限(在 Fedora/RHEL/Arch 上该组是 wheel)

危险: 不加 -a 时,usermod -G 会替换该用户的所有附加组,可能导致失去 sudo 权限。组的变更在下次登录时生效(或运行 newgrp docker)。

userdel

删除用户账户

危险Linux#
sudo userdel [-r] user
sudo userdel -r olduser

同时删除主目录和邮件池

危险: -r 会永久删除主目录及其中的文件。请先备份,或者改为锁定账户(passwd -l)。

passwd

修改密码或锁定账户

Linux#
passwd [user] | passwd -l|-u user
passwd

修改自己的密码

sudo passwd alice

重置他人的密码

sudo passwd -l alice

锁定密码登录(SSH 密钥可能仍然有效)

groupadd / gpasswd

创建用户组,或把用户移出某个组

Linux#
sudo groupadd name | sudo gpasswd -d user group
sudo groupadd developers

新建用户组

sudo gpasswd -d alice developers

把 alice 移出该组

groups / getent

列出组成员或用户所属的组

Linux#
groups [user] | getent group name
groups alice

alice 所属的组

getent group sudo

sudo 组的成员(也适用于 LDAP)

getent passwd alice

账户条目:UID、主目录、shell

visudo

安全地授予用户 sudo 权限

Linux · macOS#
sudo visudo [-f /etc/sudoers.d/file]
sudo visudo -f /etc/sudoers.d/deploy

每条规则单独一个文件

deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp

免密码执行某一条命令

visudo 会在保存前检查语法。用普通编辑器修改 /etc/sudoers 时一旦写错,所有人都可能无法使用 sudo。

chage

查看或设置密码有效期

Linux#
sudo chage [-l] [-M days] user
sudo chage -l alice

上次修改日期和过期日期

sudo chage -M 90 alice

每 90 天过期

归档与压缩

tar、gzip、xz、zip 和校验和。

tar -c

创建 .tar.gz 归档

Linux · macOS#
tar -czf archive.tar.gz files...
-c
创建
-z / -j / -J
gzip / bzip2 / xz 压缩
-f file
归档文件名(紧跟在 f 之后)
-v
列出正在加入的文件
--exclude='pattern'
排除文件
tar -czf site-2026-10-18.tar.gz site/

把文件夹打包为 gzip 压缩归档

tar -cJf logs.tar.xz --exclude='*.tmp' logs/

更小的 xz 归档,跳过临时文件

tar -x

解压 .tar.gz、.tar.xz 或 .tar.bz2

Linux · macOS#
tar -xf archive [-C dir]
-x
解压
-C dir
解压到 dir(目录须已存在)
--strip-components=1
去掉最外层文件夹
tar -xf archive.tar.gz

GNU tar 和 macOS tar 会自动识别压缩格式

tar -xzf app.tar.gz -C /opt/app --strip-components=1

解压到某个文件夹,并去掉外层包装目录

tar -t

列出归档内容或从中提取单个文件

Linux · macOS#
tar -tf archive | tar -xf archive path/in/archive
tar -tf backup.tar.gz | less

不解压直接查看里面有什么

tar -xf backup.tar.gz etc/nginx/nginx.conf

提取单个文件(路径以 -t 显示的为准)

tar --zstd

用 zstd 快速压缩

Linux · macOS#
tar --zstd -cf archive.tar.zst files...
tar --zstd -cf data.tar.zst data/

比 xz 快得多,压缩率与 gzip -9 相当或更好

zstd -d file.zst

解压单个文件

需要 GNU tar 1.31+(或较新的 bsdtar)以及 zstd 程序。

gzip / gunzip

压缩或解压单个文件

Linux · macOS#
gzip [-k] [-d] [-9] file
-k
保留原文件
-d
解压(等同于 gunzip)
-9
最高压缩率
gzip -k access.log

生成 access.log.gz,保留原文件

zcat access.log.gz | grep 404

不解压到磁盘直接读取

zgrep 500 access.log.*.gz

直接在轮转后的日志中 grep

不加 -k 时,gzip 会用 .gz 版本替换原文件。

xz / bzip2

单个文件的更高压缩率

Linux#
xz [-T0] [-9] [-d] file | bzip2 [-d] file
xz -T0 -k big.sql

使用所有 CPU 核心,保留原文件

unxz big.sql.xz

解压

zip

创建 .zip 文件

Linux · macOS#
zip -r archive.zip files... [-x pattern]
zip -r site.zip site/

压缩文件夹

zip -r site.zip site/ -x '*.git*' '*/node_modules/*'

排除路径

zip -e 使用的是老旧且安全性弱的 ZipCrypto 加密。真正需要保密请使用 7z 或 gpg。

unzip

解压 .zip 文件

Linux · macOS#
unzip [-l] [-o] archive.zip [-d dir]
unzip files.zip -d files/

解压到某个文件夹

unzip -l files.zip

只列出内容

unzip -o files.zip

不提示直接覆盖

7z

处理 .7z(以及大多数其他格式的)压缩包

Linux#
7z a|x|l archive [files]
7z x archive.7z

按完整路径解压

7z a -p backup.7z docs/

AES-256 加密压缩包(会提示输入密码)

7z l archive.rar

列出多种格式压缩包的内容

软件包:Debian/Ubuntu 上为 p7zip-full / 7zip,Fedora/Arch 上为 p7zip 或 7zip。

sha256sum

用校验和验证下载的文件

Linux#
sha256sum file | sha256sum -c SUMSFILE
sha256sum ubuntu.iso

与下载页面上的哈希值对比

sha256sum -c SHA256SUMS --ignore-missing

检查清单中列出、且你确实拥有的每个文件

macOS/BSD: macOS:shasum -a 256 file(以及 shasum -a 256 -c SUMSFILE)。

split

把大文件拆分成多份并重新合并

Linux · macOS#
split -b size file prefix
split -b 100M backup.tar.gz backup.part.

backup.part.aa、.ab……

cat backup.part.* > backup.tar.gz

重新合并

文本处理

剪切、过滤、排序、计数、转换和重组文本与 JSON。

sed s///

查找并替换文本

Linux · macOS#
sed 's/old/new/[g]' file
g
替换该行中的所有匹配,而不只是第一个
-E
扩展正则(分组无需反斜杠)
I
不区分大小写匹配(GNU)
sed 's/http:/https:/g' links.txt

输出结果;文件本身不变

sed 's|/usr/local|/opt|g' paths.txt

可用任意分隔符,处理路径时很方便

sed -E 's/([0-9]+)px/\1rem/g' style.css

复用捕获的分组

sed -i

直接修改文件

Linux · macOS#
sed -i[SUFFIX] 's/old/new/g' file
sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config

GNU sed

sed -i.bak 's/foo/bar/g' config.ini

保留 config.ini.bak;GNU 和 macOS 通用

macOS/BSD: macOS 的 sed 要求 -i 后面带参数:sed -i '' 's/foo/bar/g' file。GNU sed 会把 '' 当作脚本,所以两边都能用的写法只有 -i.bak。

sed -n / d

输出或删除指定的行

Linux · macOS#
sed -n 'Np' | sed '/regex/d'
sed -n '100,120p' big.log

第 100 到 120 行

sed '/^\s*#/d; /^$/d' app.conf

去掉注释和空行(GNU \s)

sed -n '/BEGIN CERT/,/END CERT/p' bundle.pem

两个标记之间的所有内容

awk

输出指定的列

Linux · macOS#
awk [-F sep] '{print $N}' file
-F sep
字段分隔符(默认:连续的空格/制表符)
$1 … $NF
字段;$NF 是最后一个字段,$0 是整行
NR
行号
awk '{print $1}' access.log

第一列(客户端 IP)

awk -F: '{print $1, $7}' /etc/passwd

用户和 shell

awk -F, 'NR>1 {print $2}' data.csv

CSV 第二列,跳过表头(仅限简单 CSV:字段内不能有带引号的逗号)

awk (filter & sum)

筛选行并汇总某一列

Linux · macOS#
awk 'condition {action} END {action}' file
awk '$9 >= 500' access.log

第 9 个字段(状态码)为 5xx 的行

awk '{s += $2} END {print s}' sales.txt

第 2 列求和

awk '{c[$1]++} END {for (k in c) print c[k], k}' access.log | sort -rn | head

按值计数,取前 10 名

cut

按单个字符分隔符切分字段

Linux · macOS#
cut -d DELIM -f LIST | cut -c RANGE
cut -d, -f1,3 data.csv

第 1 列和第 3 列

cut -d: -f1 /etc/passwd

所有用户名

cut -c1-10 file

每行的前 10 个字符

cut 把每个分隔符都当作字段分界,所以两个空格就意味着中间有一个空字段。以空格对齐的输出请用 awk。

sort

对行排序

Linux · macOS#
sort [-n] [-r] [-h] [-k N,N] [-t sep] [-u] file
-n
按数值
-r
倒序
-h
易读大小:2K < 1M < 3G
-k 2,2
只按第 2 个字段排序
-t ,
字段分隔符
-u
去除重复项
-V
版本号顺序:1.9 < 1.10
du -sh * | sort -h

按大小排列文件夹

sort -t, -k3,3nr data.csv

按第 3 列数值降序排列 CSV

sort -u emails.txt > unique.txt

排序并去重

uniq

统计或删除重复行

Linux · macOS#
sort file | uniq [-c] [-d] [-u]
-c
在每行前加上出现次数
-d
只显示重复出现的行
-u
只显示仅出现一次的行
sort ips.txt | uniq -c | sort -rn | head

出现频率最高的 10 行

uniq 只合并相邻的重复行,所以要先排序。

wc

统计行数、单词数或字节数

Linux · macOS#
wc [-l] [-w] [-c] [-m] file...
wc -l access.log

行数

ls | wc -l

当前文件夹中有多少项

grep -c '' file

行数统计,包括末尾没有换行符的最后一行

tr

转换或删除字符

Linux · macOS#
tr [-d] [-s] 'set1' ['set2']
tr 'a-z' 'A-Z' < in.txt

转为大写

tr -d '\r' < windows.txt > unix.txt

去掉 Windows 的 CRLF 换行符

tr -s ' ' < file

压缩连续的空格

tr '\n' ',' < list.txt

用逗号连接各行

tr 只读取标准输入,所以要用 < 把文件重定向进来。

xargs

把输入的每一行变成命令参数

Linux · macOS#
command | xargs [-0] [-n N] [-P N] [-I {}] cmd
-0
输入以 NUL 分隔(与 find -print0 搭配);文件名带空格也安全
-n N
每条命令最多 N 个参数
-P N
并行运行 N 条命令
-I {}
把 {} 替换为每一行输入
-r
输入为空时不运行命令(GNU)
find . -name '*.log' -print0 | xargs -0 rm -f

安全删除找到的文件

cat urls.txt | xargs -n 1 -P 4 curl -sO

每次同时下载 4 个

ls *.png | xargs -I {} cp {} /backup/{}

每项执行一次命令

macOS/BSD: 即使输入为空,GNU xargs 也会运行一次命令,除非加上 -r;macOS xargs 默认跳过空输入,并为兼容性接受 -r。

jq

读取和筛选 JSON

Linux · macOS#
jq [-r] 'filter' file
.
美化输出
-r
原始字符串,不带引号
-c
紧凑格式,每个结果一行
.[]
遍历数组
select(cond)
保留匹配的项
jq . response.json

美化输出

jq -r '.items[].name' data.json

每行一个名称

jq -r '.[] | select(.active) | .email' users.json

先筛选,再取某个字段

curl -s https://api.github.com/repos/jqlang/jq | jq '.stargazers_count'

直接处理 API 返回的数据

用 apt/dnf install jq 安装。较新的 macOS 已自带。

paste

连接多行或并排合并文件

Linux · macOS#
paste [-s] [-d delim] file...
paste -sd, ids.txt

所有行用逗号连接

paste names.txt emails.txt

两个文件并排成两列

comm

两个列表的共有行(或独有行)

Linux · macOS#
comm [-1] [-2] [-3] sorted1 sorted2
comm -12 <(sort a.txt) <(sort b.txt)

两边都有

comm -23 <(sort a.txt) <(sort b.txt)

只在 a.txt 中

seq

生成数字序列

Linux · macOS#
seq [first [step]] last
seq 1 5

1 到 5,每行一个

seq -w 1 10

补零:01 … 10

for i in $(seq 1 3); do echo "run $i"; done

循环计数器

base64

Base64 编码或解码

Linux · macOS#
base64 [-d] [-w 0] [file]
printf '%s' 'user:pass' | base64

编码(用 printf 可避免末尾多出换行符)

echo dXNlcjpwYXNz | base64 -d

解码

base64 -w 0 image.png > image.b64

不换行(GNU 默认每 76 个字符换行)

macOS/BSD: macOS 的 base64 默认不换行,也没有 -w。解码用 -d(旧版 macOS 用 -D)。

iconv

转换文本编码(例如转为 UTF-8)

Linux · macOS#
iconv -f FROM -t TO file
iconv -f WINDOWS-1252 -t UTF-8 old.csv > new.csv

修复 Excel 导出文件的乱码

iconv -l

列出支持的编码

shuf

打乱行顺序或随机选取行

Linux#
shuf [-n N] file
shuf -n 1 names.txt

随机一行

shuf -i 1-100 -n 5

从 1 到 100 中随机取五个数

服务与日志

systemd 服务:启动、停止、设置开机自启,以及用 journalctl 查看日志。

systemctl status

检查服务是否在运行

Linux#
systemctl status|is-active|is-enabled unit
systemctl status nginx

状态、PID、内存和最近几行日志

systemctl is-active --quiet nginx && echo up

用于脚本

systemctl start

启动、停止、重启或重新加载服务

Linux#
sudo systemctl start|stop|restart|reload unit
sudo systemctl restart nginx

完全重启

sudo systemctl reload nginx

重新读取配置而不断开连接(如果服务支持)

尽量在重启前先测试配置,例如 sudo nginx -t,以免一个笔误就让网站宕掉。

systemctl enable

设置服务开机自启(或取消自启)

Linux#
sudo systemctl enable|disable [--now] unit
sudo systemctl enable --now docker

设为开机自启并立即启动

sudo systemctl disable --now cups

立即停止并取消开机自启

sudo systemctl mask bluetooth

彻底禁止它被启动(用 unmask 撤销)

systemctl list-units

列出运行中和失败的服务

Linux#
systemctl list-units [--type=service] [--state=…] | systemctl --failed
systemctl --failed

哪些出了问题

systemctl list-units --type=service --state=running

哪些正在运行

systemctl list-unit-files --state=enabled

哪些开机自启

systemctl edit

修改服务单元(并重新加载 systemd)

Linux#
sudo systemctl edit unit | sudo systemctl daemon-reload
sudo systemctl edit nginx

以附加配置覆盖,软件包升级后依然保留

systemctl cat nginx

单元文件及其所有覆盖配置

sudo systemctl daemon-reload

手动编辑单元文件后需要执行

.service file

把你自己的应用作为服务运行

Linux#
/etc/systemd/system/<name>.service
[Unit]
Description=My app
After=network.target

[Service]
User=app
WorkingDirectory=/srv/app
ExecStart=/srv/app/bin/server
Restart=on-failure

[Install]
WantedBy=multi-user.target

然后:sudo systemctl daemon-reload && sudo systemctl enable --now myapp

journalctl

查看服务和系统日志

Linux#
journalctl [-u unit] [-f] [-n N] [--since …] [-p level] [-b]
-u unit
单个服务
-f
跟踪
-n N
最后 N 行
--since '1 hour ago'
也可以写:today、yesterday、2026-10-18 09:00
-p err
优先级为 err 及更严重的
-b / -b -1
本次启动 / 上一次启动
-e
跳到末尾
journalctl -u nginx -f

跟踪单个服务

journalctl -u myapp --since '10 min ago'

最近一段时间

journalctl -b -1 -p err

崩溃前那次启动中的错误

journalctl --vacuum

缩减 systemd 日志

Linux#
journalctl --disk-usage | sudo journalctl --vacuum-size=SIZE | --vacuum-time=TIME
journalctl --disk-usage

日志占用了多少空间

sudo journalctl --vacuum-size=500M

已归档日志最多保留 500 MB

sudo journalctl --vacuum-time=14d

删除两周前的已归档日志

要设置永久上限,请在 /etc/systemd/journald.conf 中设置 SystemMaxUse=。

/var/log

找到传统的日志文件

Linux#
sudo tail -f /var/log/<file>
sudo tail -f /var/log/syslog

Debian/Ubuntu 上的通用日志(Fedora/RHEL 上是 /var/log/messages)

sudo tail -f /var/log/auth.log

Debian/Ubuntu 上的登录和 sudo 记录(RHEL 上是 /var/log/secure)

部分发行版(Fedora、Arch)在未安装 rsyslog 时只把日志保存在 journal 中。

shutdown / reboot

重启或关机

Linux#
sudo shutdown -r|-h [now|+min|hh:mm] [message] | sudo reboot
sudo reboot

立即重启

sudo shutdown -r +10 'Kernel update'

10 分钟后重启,并通知已登录的用户

sudo shutdown -c

取消已计划的关机

sudo shutdown -h now

关机

定时任务:cron、at、定时器

按计划运行命令,或稍后运行一次。

cron syntax

编写 cron 计划行

Linux · macOS#
minute hour day-of-month month day-of-week command
30 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

每天 02:30 运行,保留输出

*/15 * * * * /usr/local/bin/check.sh

每 15 分钟

0 9 * * 1-5 /usr/local/bin/report.sh

周一至周五 09:00

@reboot /usr/local/bin/startup.sh

开机时运行一次

cron 运行时 PATH 很精简,也不加载 shell 配置文件:请使用绝对路径。命令中的 % 必须转义为 \%。

crontab -r

删除你的 crontab(小心)

危险Linux · macOS#
crontab -r
crontab -l > ~/crontab.bak && crontab -r

删除前先备份

crontab ~/crontab.bak

从文件恢复

危险: 会不加提示地删除你的所有 cron 任务,而且键盘上 r 就挨着 e。部分 cron 实现提供 -i 选项,删除前会先询问(crontab -ri)。

/etc/cron.d

系统级 cron 任务

Linux#
/etc/crontab, /etc/cron.d/*, /etc/cron.{hourly,daily,weekly,monthly}/
0 3 * * * root /usr/local/bin/cleanup.sh

/etc/cron.d/cleanup 中的一行:注意多出的用户字段

ls /etc/cron.daily/

由 run-parts 每天运行一次的脚本

在 Debian 和 Ubuntu 上,/etc/cron.d 中文件名带点的文件会被忽略,所以请命名为 backup,而不是 backup.cron。

at

稍后运行一次命令

Linux#
at TIME | atq | atrm N
echo 'systemctl restart myapp' | sudo at 02:00

今晚凌晨 2 点

echo './report.sh' | at now + 30 minutes

半小时后

atq

待执行的任务

atrm 3

取消任务 3

需要安装 at 软件包并运行 atd 服务。

systemd timers

用 systemd 定时器代替 cron

Linux#
systemctl list-timers | <name>.timer with OnCalendar=
systemctl list-timers

所有定时器及其下次触发时间

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

backup.timer 放在 backup.service 旁边;Persistent 会在停机后补上错过的运行

systemd-analyze calendar 'Mon..Fri 09:00'

查看 OnCalendar 表达式的含义

sleep

等待一段时间再执行下一条命令

Linux · macOS#
sleep N[s|m|h|d]
sleep 5 && curl -s localhost:8080/health

给服务留出启动时间

sleep 2m

GNU 和当前的 macOS 都支持时间单位后缀

Shell 基础(bash)

管道、重定向、通配符、变量、历史记录,以及最省时间的快捷键。macOS 默认使用 zsh:这里的内容几乎都适用,只有 shopt、help 和 bash 4 的特性除外(macOS 自带的是 bash 3.2)。

|

把一条命令的输出传给另一条命令

Linux · macOS#
command1 | command2
ps aux | grep nginx

过滤列表

history | grep 'docker run'

查找以前运行过的命令

set -o pipefail

在脚本中:管道中任何一部分失败都算失败,而不只看最后一个

> and >>

把输出保存到文件(覆盖或追加)

Linux · macOS#
command > file | command >> file
ls -l > listing.txt

覆盖(文件不存在则创建)

echo 'done' >> progress.log

追加

set -o noclobber

让 > 拒绝覆盖已有文件(>| 强制覆盖)

shell 会在命令运行前清空文件,所以 sort file > file 只会得到一个空文件。请先写入新文件名,再用 mv。

2> and 2>&1

重定向错误输出,或把错误和输出合在一起

Linux · macOS#
command 2> err.log | command > all.log 2>&1 | command &> all.log
find / -name x 2>/dev/null

丢弃错误信息

./build.sh > build.log 2>&1

输出和错误写入同一个文件(顺序很重要:先 >,再 2>&1)

./build.sh &> build.log

bash 中的等效简写

<, <<EOF, <<<

从文件、文本块或字符串提供输入

Linux · macOS#
command < file | command <<'EOF' … EOF | command <<< "string"
mysql mydb < dump.sql

文件作为输入

cat > config.yml <<'EOF'
port: 8080
host: $HOST stays literal
EOF

给 'EOF' 加引号后,$变量 不会被展开

grep -c a <<< "banana"

here-string

&& || ;

按条件依次运行命令

Linux · macOS#
a && b | a || b | a ; b
make && sudo make install

只有构建成功才安装

cd /srv/app || exit 1

cd 失败时终止脚本

(cd frontend && npm run build)

圆括号表示子 shell,所以当前目录不会改变

$( ) $(( )) <( )

使用命令的输出或进行算术运算

Linux · macOS#
$(command) | $((expression)) | <(command)
echo "Today is $(date +%A)"

命令替换

echo $(( 1024 * 4 ))

整数运算

diff <(ls dir1) <(ls dir2)

进程替换:把输出当作临时文件

反引号 `command` 是 $(command) 的旧写法;$( ) 可以嵌套,可读性也更好。

* ? [ ] { }

用通配符匹配多个文件

Linux · macOS#
* any string | ? one char | [abc] one of | {a,b} each word
ls *.jpg

当前文件夹中的所有 JPG

rm photo-??.png

photo-01.png … photo-99.png

cp config.{yml,yml.bak}

花括号展开:cp config.yml config.yml.bak

shopt -s globstar; ls **/*.md

** 匹配任意深度(bash 4+)

通配符默认不匹配以点开头的文件(shopt -s dotglob 可改变这一点)。如果没有匹配项,bash 会原样传递模式,除非设置了 shopt -s nullglob。

' ' vs " "

正确地给字符串和变量加引号

Linux · macOS#
'literal' | "expands $var and $(cmd)" | \ escapes one character
echo 'Cost: $5'

单引号:什么都不展开

echo "Home is $HOME"

双引号:变量会展开,空格会保留

cp "$file" "$dest/"

存放路径的变量一定要加引号:不加引号时遇到空格就会出错

VAR=value

设置和使用 shell 变量

Linux · macOS#
name=value (no spaces around =) | "$name" | "${name}"
name="Ada"; echo "Hi $name"

设置并使用

echo "${PORT:-8080}"

未设置或为空时使用默认值

file=report.tar.gz; echo "${file%%.*}" "${file##*/}"

去掉扩展名 / 去掉目录

echo "${#name}"

字符串长度

export

设置环境变量

Linux · macOS#
export NAME=value | NAME=value command | unset NAME
export NODE_ENV=production

对从当前 shell 启动的所有程序可见

DEBUG=1 ./app

只对这一条命令生效

printenv | sort

列出环境变量

unset DEBUG

删除变量

shell 退出后就会失效。要永久保留,请把 export 写入 ~/.bashrc(交互式 shell)或 ~/.profile(登录 shell)。

$PATH

把文件夹加入 PATH

Linux · macOS#
export PATH="dir:$PATH"
echo "$PATH" | tr : '\n'

每行一个条目

export PATH="$HOME/.local/bin:$PATH"

把你自己的 bin 文件夹加到最前面(写入 ~/.bashrc)

hash -r

移动可执行文件后清除缓存的命令位置

alias / source

创建快捷别名并重新加载 shell 配置

Linux · macOS#
alias name='command' | source file
alias ll='ls -alF'

写入 ~/.bashrc 以永久保留

source ~/.bashrc

不开新终端即可应用更改(等同于 . ~/.bashrc)

\ls

绕过别名,运行真正的 ls

$?

检查上一条命令是否成功

Linux · macOS#
echo $? (0 = success)
grep -q root /etc/passwd; echo $?

0 表示找到,1 表示没找到,2 表示出错

set -euo pipefail

放在脚本开头:遇到错误、未设置的变量或失败的管道时停止

history, !!

重复使用之前的命令

Linux · macOS#
history | !! | !$ | !N | !prefix | ^old^new
sudo !!

用 sudo 重新运行上一条命令

cd !$

使用上一条命令的最后一个参数

!42

重新运行历史记录中的第 42 条

^foo^bar

把上一条命令中的 foo 替换为 bar 后重新运行

设置 HISTCONTROL=ignorespace 后(Ubuntu 默认的 ignoreboth 已包含它),以空格开头输入的命令不会被保存:适合含有密码等机密信息的命令。

Ctrl+R, Ctrl+A …

终端快捷键(bash/readline)

Linux · macOS#
Emacs-style readline keys (the default)
Ctrl+R
反向搜索历史记录;再按一次查找更早的匹配
Ctrl+A / Ctrl+E
跳到行首 / 行尾
Ctrl+U / Ctrl+K
剪切到行首 / 行尾
Ctrl+W
剪切前一个单词
Ctrl+Y
粘贴剪切的内容
Alt+B / Alt+F
后退 / 前进一个单词
Alt+.
插入上一条命令的最后一个参数
Ctrl+L
清屏
Ctrl+C
取消正在运行的命令
Ctrl+D
输入结束;在空行上按下会退出 shell
Tab Tab
显示补全候选
bind -P | less

列出所有按键绑定

man / --help

获取任意命令的帮助

Linux · macOS#
man [section] cmd | cmd --help | help builtin | apropos word
man rsync

完整手册;按 / 搜索,按 q 退出

man 5 crontab

第 5 节:文件格式,而不是命令

help cd

bash 内置命令没有单独的 man 手册页

apropos partition

哪些命令提到了某个词

#!/usr/bin/env bash

编写并运行 shell 脚本

Linux · macOS#
#!/usr/bin/env bash, chmod +x, ./script.sh
#!/usr/bin/env bash
set -euo pipefail
name="${1:-world}"
if [[ -f "$name.txt" ]]; then
  echo "found $name.txt"
fi
for f in *.log; do
  echo "$f"
done

参数、条件测试和循环

chmod +x script.sh && ./script.sh Ada

设为可执行并运行

bash -x script.sh

运行时逐行跟踪

$1 … $9 是参数,"$@" 是全部参数,$# 是参数个数。[[ ]] 是 bash 语法;POSIX sh 脚本请用 [ ]。

clear / reset

清屏或修复显示错乱的终端

Linux · macOS#
clear | reset
reset

用 cat 查看二进制文件后终端一直输出乱码时使用

静态参考资料,在你的浏览器中运行;搜索内容不会发送到任何地方。 浏览全部免费工具.

发现问题,或者觉得哪里可以更好?每条消息我们都会阅读,并尽快修复。

这份 Linux 命令速查表按你要完成的工作对 200 多条命令进行分类:目录切换和文件管理、权限、进程、磁盘空间、网络、软件包、用户、压缩归档、搜索、文本处理、systemd 服务和日志、cron,以及把这些串联起来的 bash 基础。每个条目都给出语法、你真正会用到的参数(附一行说明)、可复制的示例,并在必要时给出警告。可以按任务(“free disk space”、“what is using port 8080”)或命令名搜索,也可以直接链接到任意条目。

参数说明依据 GNU coreutils、util-linux、procps-ng、iproute2、systemd 和 bash 的手册,这也是 Ubuntu、Debian、Fedora、RHEL、Arch 和 openSUSE 所附带的工具。macOS 行为不同的地方会用蓝色注释说明,因为 sed -i、date -d、stat -c 和 xargs 正是在一个系统上写的脚本到另一个系统上就出错的经典位置。它覆盖的是常用的 90%,不能替代 man 手册:对于不常用的选项,man <command> 仍然是权威。

使用方法

  1. 在搜索框中输入任务或命令(按 / 可跳到搜索框)。所有词都必须匹配,所以“tar extract”会把结果缩小到 tar 相关条目。
  2. 点击分类标签跳到网络、软件包等主题,或勾选“只看危险命令”,查看所有可能销毁数据或把你锁在系统外的命令。
  3. 点击示例旁的“复制”,然后把示例中的文件名和主机名换成你自己的。
  4. 点击条目旁的 # 获取直达链接,例如 /tools/linux-commands-cheat-sheet#rsync。
  5. 使用“打印 / 另存为 PDF”获取不含网站导航的紧凑双栏版本。

常见问题

最先该学哪些 Linux 基础命令?

先从目录切换和文件操作开始:pwd、ls、cd、mkdir、cp、mv、rm、cat 和 less。然后是 man(帮助)、sudo,用于搜索的 grep 和 find,用于权限的 chmod 和 chown,用于进程的 ps、top 和 kill,用于磁盘空间的 df 和 du,以及用于远程机器的 ssh 和 scp。尽早学会管道(|)和重定向(> 和 >>),因为它们能把其他所有命令组合起来。

Linux 上如何查看磁盘空间?

运行 df -h,以易读的单位查看每个已挂载文件系统的剩余空间。要找出是什么占用了空间,在目录中运行 du -h -d 1 | sort -h:它会列出各子目录,最大的排在最后。如果 df 显示磁盘已满,而 du 却找不到什么,那很可能是某个已删除的文件仍被进程打开着;sudo lsof +L1 可以列出这些文件。

如何查找占用某个端口的进程?

运行 sudo ss -tulpn,列出所有正在监听的 TCP 和 UDP 端口及其所属程序,或用 sudo lsof -i :8080 查看单个端口。sudo 很关键:不加它,你只能看到自己进程的名称。ss 已取代 netstat,后者在安装了 net-tools 软件包的系统上仍然可用。

kill 和 kill -9 有什么区别?

kill PID 发送 SIGTERM,请求进程退出,并让它完成清理工作:刷新文件、释放锁、关闭连接。kill -9 PID 发送 SIGKILL,由内核立即强制执行,进程无法捕获或忽略,因此不会进行任何清理。先用普通的 kill,等几秒钟,把 -9 留给那些不理会 SIGTERM 的进程。

为什么 sed -i 在 Mac 上不能用?

macOS 自带的是 BSD sed,它的 -i 需要一个备份扩展名参数。在 macOS 上要写 sed -i '' 's/old/new/g' file;而在 Linux 的 GNU sed 上,同样的命令会失败,因为它会把 '' 当作脚本。两边都能用的写法是 sed -i.bak 's/old/new/g' file,它会保留一个备份副本,之后可以删除。

这些命令在所有 Linux 发行版上都一样吗?

几乎都一样:核心工具在各处都来自相同的 GNU 和 util-linux 项目。不同的是软件包管理器(Debian 和 Ubuntu 用 apt,Fedora 和 RHEL 用 dnf,Arch 用 pacman,openSUSE 用 zypper,在“软件包”表格中并列展示)、部分日志文件路径、管理员组(sudo 还是 wheel)以及防火墙前端(ufw 还是 firewalld)。Alpine 和基于 BusyBox 的系统使用精简版工具,参数更少。

可能毁掉系统的命令,以及避免出事的习惯

几乎所有破坏都出自少数几条命令:路径写错或为空的 rm -rf,指向错误磁盘的 dd 或 mkfs,作用于系统目录的 chmod -R 777 或 chown -R,源和目标写反了的 rsync --delete 或类似 robocopy 的镜像操作,把 crontab -e 打成 crontab -r,不带 -a 的 usermod -G,以及 -delete 放错位置的 find。速查表中每一条都标记为“危险”,并说明具体会怎样出错。

能避免大多数事故的习惯,是先运行无害的版本。执行 rm -rf 之前,先对同一路径运行 ls。执行 find … -delete 之前,先用 -print 运行同样的 find。执行 rsync --delete 之前,加上 -n 做一次试运行。执行 dd 或 mkfs 之前,运行 lsblk 并把设备名读两遍。在脚本中用 ${DIR:?} 而不是 $DIR,这样变量为空时脚本会中止,而不是把路径变成 /。

还有两个 shell 设置也有帮助:在脚本开头写 set -euo pipefail,遇到第一个错误就停止,而不是带着错误状态继续执行;set -o noclobber 则会让 > 拒绝覆盖已有文件。

GNU 与 macOS(BSD):同一命令行为不同的地方

macOS 是 Unix,但它的命令行工具来自 FreeBSD 而不是 GNU,这些差异恰恰会在你照搬 Linux 教程里的命令时暴露出来:

• sed -i 在 macOS 上需要一个参数(sed -i '' …);-i.bak 两边都能用。

• macOS 的 date 没有 -d;用 date -r <epoch> 转换时间戳,用 date -v-2d 表示相对日期。

• stat 使用 -f 和不同的格式字母,而不是 GNU 的 -c。

• macOS 上的 xargs 默认在输入为空时不执行命令,而 GNU xargs 除非加上 -r,否则仍会执行一次。

• du 在两边都支持 -d 1,但只有 GNU 接受 --max-depth;macOS 的 ps 没有 --sort(改用 ps aux -m 或 -r)。

• 原装 macOS 没有 head -n -5、tac、free、ip、ss、timeout 和 watch。

如果在 Mac 上需要 GNU 的行为,Homebrew 的 coreutils、gnu-sed 和 findutils 软件包会安装带 g 前缀的 GNU 版本(gsed、gdate、gstat、gxargs)。

看懂权限,选对 chmod

ls -l 用十个字符显示权限,例如 -rwxr-x---。第一个字符是类型(- 文件,d 目录,l 链接);后面九个字符分为三组,分别是所有者、所属组和其他所有人的读、写和执行权限。换成数字,r 是 4,w 是 2,x 是 1,每组相加,所以 rwxr-x--- 就是 750。

常见权限:普通文件 644,目录和脚本 755,私钥和存放机密信息的文件 600,~/.ssh 这样的私有目录 700。对目录而言,x 表示“允许进入”,所以目录需要 x,而普通文件不需要。如果想在应用之前检查权限,chmod 计算器可以在符号形式和八进制形式之间换算。

相关免费工具

  • CMD vs PowerShell vs Bash — 同一任务在命令提示符、PowerShell 和 bash 中的写法并排对照:文件、grep、环境变量、进程、网络、服务和脚本编写。
  • Chmod 计算器 — 勾选读、写、执行复选框,得到八进制权限值和 chmod 命令,或解读 755、644 和 rwxr-xr-x。
  • Cron 表达式生成器 — 用下拉菜单生成 cron 定时计划,或粘贴现有表达式,用通俗语言解读,并查看接下来 10 次运行时间(本地时区和 UTC)。免费,在浏览器中运行。
  • 子网计算器 — 计算任意 CIDR 的网络地址、广播地址、主机范围和掩码;用 VLSM 划分网络,展开 IPv6 地址,查找重叠的地址段。
  • Git 速查表 — 按你想做的事整理 Git 命令:撤销上一次提交、重命名分支、删除远程分支。优先给出新式 switch/restore 命令并附经典写法,危险操作有醒目标记。