“Port already in use” on a server
The first line of the reverse lookup: ss -tulnp | grep :8080 to find the PID, then kill <PID>, or straight to kill -9 $(lsof -t -i :8080).
Guide
Linux Cheat Sheet orders the 160 commands you type in a terminal every day into eight groups — files and directories, viewing and editing content, text processing, permissions and users, processes and services, networking, compression and archiving, and system information and administration — each with a one-line explanation and a few lines of copy-ready examples; commands with a large option set such as ls, find, grep, sed, awk, tar, curl, ss and journalctl also carry a common-options table that expands in place.
Updated 2026-09-094 sources9 min read
Linux Cheat Sheet orders the 160 commands you type in a terminal every day into eight groups — files and directories, viewing and editing content, text processing, permissions and users, processes and services, networking, compression and archiving, and system information and administration — each with a one-line explanation and a few lines of copy-ready examples; commands with a large option set such as ls, find, grep, sed, awk, tar, curl, ss and journalctl also carry a common-options table that expands in place.
It solves two kinds of lookup. One is knowing the command name but forgetting the arguments (search tar, chmod). The other is knowing only what you want to see — “which process is on port 8080”, “which directory is using the most disk”, “why did this service fail to start” — and for that there is a dedicated “I want to see… → which command” reverse lookup: the goal comes first, then 2–3 commands that get you there, ordered from recommended to compatible.
At the bottom of the page there is a simulated terminal that runs in the browser: an in-memory file system plus a shell interpreter for 60+ commands, with pipes, redirection, wildcards and a common subset of sed/awk, and 8 practice levels from building a directory tree to counting logs with pipes. It never touches your computer and has no network, so a mistyped rm -rf only resets a level.
help lists all commands the simulator supports, and Tab completes file names.Searching “port” matches both the command table and the reverse lookup:
A complete solution to level 8, “pipeline combos”, in the simulated terminal:
I want to see: which process is using a port
ss -tulnp | grep :8080
lsof -i :8080
netstat -tulnp | grep 8080 older systems
Networking › ss -tulnp listening ports and their processes (replaces netstat)
Networking › lsof -i :<port> which process is using a portuser@toolun-lab:~$ awk '{print $2}' access.log | sort | uniq -c | sort -rn
3 /index.html
2 /api/list
2 /about
✔ Passed: pipeline combos: the most visited paths.Two Unix design principles shape this table. “Everything is a file”: devices, process information (/proc) and sockets are all exposed as files, which is why odd-looking uses such as cat /proc/cpuinfo, ls -l /dev/sd* and echo > /dev/tcp/host/port all work. “Each program does one thing and does it well”: grep only filters, sort only sorts, uniq only merges adjacent duplicates, wc only counts — each is small on its own, and their power comes from chaining them with pipes.
That is why | appears so often in the examples: awk '{print $1}' access.log | sort | uniq -c | sort -rn | head builds “the most visited IPs” out of five small programs. Understanding the input and output of each stage is more useful than memorizing the whole command.
Every process starts with three open “files”: standard input (0), standard output (1) and standard error (2). > writes standard output to a file, 2> handles the error stream, 2>&1 merges errors into output and &> is bash shorthand. The most common everyday combination is cmd > out.log 2>&1 &: normal output and errors both go to the log, and the job goes to the background. Forgetting 2>&1 is the number one reason for “why is there no error in the log”.
The first column of ls -l, such as -rwxr-xr-x, has four parts: the type (- file, d directory, l link), then read (4), write (2) and execute (1) for the owner, the group and everyone else. Adding the three digits gives the numeric form: rwx=7, r-x=5, r--=4, so 755 is “full control for me, read and execute for everyone else” and 644 is “read and write for me, read-only for the rest”. For a directory, x means “may enter”: a directory without x cannot be listed even if it has r. 600/700 are for private keys and ~/.ssh — SSH clients reject key files that are too broadly readable. More combinations can be assembled with the chmod calculator.
The name of kill is misleading: it only sends a signal to a process. The default TERM (15) means “please exit”, giving the program a chance to save its state; KILL (9) is the kernel terminating it with no chance at all — so kill first, wait a few seconds, and only then kill -9. HUP (1) is conventionally “reload the configuration” for daemons; nginx -s reload uses it underneath.
Modern distributions manage services with systemd: systemctl starts, stops and enables them at boot, and journalctl collects their logs in one place. The fixed path for “the service will not start” is systemctl status for the state and the last few log lines → journalctl -u <service> -n 100 for the full error → ss -tlnp to see whether the port is already taken.
ifconfig, netstat, route and arp belong to the unmaintained net-tools and are no longer installed by default on new systems; their replacements in iproute2 are ip addr, ss, ip route and ip neigh. The cheat sheet lists both, and the reverse lookup puts the new tools first. The five letters of ss -tulnp stand for TCP, UDP, listening, numeric ports and processes — almost always the opening move for a port problem.
GNU sed accepts -i without an argument; BSD sed (the one macOS ships) requires a backup suffix after -i, so you write sed -i '' 's/a/b/' file. Similar differences include date -d (GNU) versus date -v (BSD), and readlink -f not existing on older macOS. The cheat sheet follows the GNU versions and notes macOS differences in the entry remarks; brew install coreutils gnu-sed installs the GNU ones.
yast), desktop-environment commands and language-specific CLIs are not included.sed only covers s///, N,Mp and Nd, and awk only {print $N}; there is no network (curl, ssh and apt explain why), no real processes (ps, top and kill return fixed demo data) and no interactive editors (write files with echo > or cat >>).The first line of the reverse lookup: ss -tulnp | grep :8080 to find the PID, then kill <PID>, or straight to kill -9 $(lsof -t -i :8080).
The text-processing group is a complete kit, from grep -A3 -B1 for context through awk/sort/uniq -c for statistics to tail -F for logs that rotate; practice levels 3 and 8 are exactly these two jobs.
tar -czvf → scp / rsync -avz → tar -xzvf -C /var/www/, three adjacent entries; the trap in rsync --delete is in the remarks.
Walk the system information and administration group in order — cat /etc/os-release, nproc, free -h, df -h, ss -tlnp, systemctl list-units — and you have a working picture in ten minutes.
Essentially no. Linux has no recycle bin, and rm releases the inode directly. Before touching an important directory, confirm the path with ls; in scripts, quote variables and guard against empty ones (rm -rf "${DIR:?}"/), or replace rm with a tool such as trash-cli.
Usually the terminal or the file encoding does not match. Run file <filename> first to see the encoding, convert GBK files to UTF-8 with iconv -f GBK -t UTF-8 and search again; grep -a treats files that were misdetected as binary as text.
The columns of ss -tulnp are Netid, State, Recv-Q, Send-Q, Local Address:Port, Peer Address:Port and Process. To find a port, look at Local Address:Port (*:8080 or 0.0.0.0:8080 means all interfaces); to find the process, look at the last column, users:(("node",pid=842,fd=18)).
It runs in the browser, has no network stack and should not send requests on your behalf; those commands return an explanation and point to the matching entry in the cheat sheet. The focus of the levels is files, text and permissions, all of which work fully in the in-memory file system.
Reading files you already have permission for needs nothing; changing system directories (/etc, /usr), binding to ports below 1024, reading other users' process details, and managing services and packages all need root. sudo runs one command as root, which is safer than switching to root for a long session.
The cheat data, the reverse lookup and the simulated terminal are all static content downloaded with the page and run locally in your browser; searching, copying and practicing send no requests. Favorites are stored in this browser's localStorage. The file system of the simulated terminal exists only in the current page's memory, clears on refresh, and never reads or writes your real files.
ls, cp, sort and cut.ss(8), ip(8), find(1) and grep(1).Updated 2026-09-09
160 Linux and shell commands grouped by files, text, permissions, processes, networking, archives, and system tasks, with examples and a practice terminal
Look up by output goal: say what you want to know and you get 2–3 commands that show it, newest first and recommended before compatible.
pwd # /var/www/site
ls -la # 详细 + 隐藏文件 ls -lh # 人类可读的大小 ls -lt | head # 按修改时间倒序看最新的
| -l | 长格式:权限、所有者、大小、时间 |
| -a | 含以 . 开头的隐藏文件 |
| -h | 大小用 K/M/G |
| -t | 按修改时间排序 |
| -S | 按大小排序 |
| -R | 递归子目录 |
| -d | 只列目录本身不进入 |
cd /var/log cd .. # 上一级 cd - # 回到上一个目录 cd # 回家目录(同 cd ~)
mkdir -p app/src/{components,utils}
mkdir -m 700 private| -p | 递归创建,已存在不报错 |
| -m | 指定权限 |
| -v | 显示创建了什么 |
touch README.md touch -d "2026-01-01" old.log # 指定时间
cp a.txt b.txt cp -r src/ backup/ # 目录要 -r cp -a /etc/nginx ~/nginx-bak # 保留权限与时间
| -r / -R | 递归复制目录 |
| -a | 归档:等于 -dR --preserve=all |
| -i | 覆盖前询问 |
| -n | 不覆盖已存在文件 |
| -u | 只在源更新时复制 |
| -v | 显示过程 |
mv old.txt new.txt # 重命名 mv *.log logs/ # 批量移动 mv -i a.txt dir/ # 覆盖前询问
| -i | 覆盖前询问 |
| -n | 不覆盖 |
| -f | 强制覆盖 |
| -v | 显示过程 |
rm file.txt rm -r build/ # 删目录 rm -rf node_modules # 不确认、忽略不存在
rm 不进回收站。rm -rf 前先 echo 一下路径变量是否为空:rm -rf "$DIR"/ 在 DIR 为空时等于 rm -rf /。
| -r | 递归删除目录 |
| -f | 不询问、忽略不存在 |
| -i | 逐个确认 |
| -d | 删除空目录 |
| -- | 之后的参数不当选项(删以 - 开头的文件) |
rmdir empty-dir rmdir -p a/b/c # 连同变空的父目录
ln -s /opt/app/current ~/app ln -sf new-target link # 覆盖已有链接 readlink -f link # 看链接指向哪
find . -name "*.log"
find /var -type f -size +100M # 大于 100MB 的文件
find . -mtime -7 -name "*.js" # 7 天内修改过
find . -name "*.tmp" -delete
find . -type f -exec chmod 644 {} \;| -name / -iname | 按名字(-iname 忽略大小写) |
| -type f|d|l | 文件 / 目录 / 链接 |
| -size +10M / -1k | 按大小 |
| -mtime -N / +N | N 天内 / N 天前修改 |
| -maxdepth N | 限制深度 |
| -exec cmd {} \; | 对每个结果执行命令 |
| -delete | 删除匹配项 |
| -empty | 空文件或空目录 |
sudo updatedb locate nginx.conf
which python3 type ls # bash 内建,能看出别名 / 内建 / 外部命令 command -v node # 脚本里判断命令是否存在
tree -L 2 tree -a -I "node_modules|.git" # 排除
file photo.bin # photo.bin: JPEG image data, ...
stat app.log stat -c "%s %n" * # 只要大小和名字
du -sh . du -sh * | sort -rh | head # 谁最占地方 du -h --max-depth=1 /var
| -s | 只显示总计 |
| -h | 人类可读 |
| --max-depth=N | 限制层级 |
| -a | 含文件 |
df -h df -h /home df -i # inode 用量(文件数太多时满)
basename /var/log/syslog # syslog basename report.pdf .pdf # report dirname /var/log/syslog # /var/log
realpath ../config.yml
rsync -avz --progress src/ user@host:/srv/app/ rsync -av --delete ./dist/ /var/www/site/ # 目标多余文件也删 rsync -avn src/ dst/ # -n 只预演
源目录末尾有无 / 含义不同:src/ 同步内容,src 同步目录本身。
| -a | 归档模式(递归 + 保留属性) |
| -v | 显示过程 |
| -z | 传输压缩 |
| --delete | 删除目标端多余文件 |
| -n / --dry-run | 只预演 |
| --exclude=PAT | 排除 |
| -P | 进度 + 断点续传 |
scp app.tar.gz user@1.2.3.4:/tmp/ scp -r user@host:/var/log/app ./logs scp -P 2222 file user@host:~ # 指定端口(大写 P)
cat config.yml cat -n app.js # 带行号 cat a.txt b.txt > all.txt # 拼接
| -n | 行号 |
| -A | 显示不可见字符(^M 就是 CRLF) |
| -s | 压缩连续空行 |
less /var/log/syslog # /关键词 搜索 n 下一个 G 到末尾 g 到开头 q 退出 F 跟随(像 tail -f)
| -N | 显示行号 |
| -S | 不折行 |
| +F | 进入即跟随模式 |
| -i | 搜索忽略大小写 |
head -n 20 app.log head -c 100 file.bin # 前 100 字节 head -n -5 file # 除了最后 5 行
tail -n 50 app.log tail -f /var/log/nginx/access.log tail -F app.log # 文件被轮转后继续跟随
| -n N | 后 N 行 |
| -f | 跟随追加 |
| -F | 跟随并处理文件重建 |
| -n +N | 从第 N 行起到末尾 |
wc -l access.log ls | wc -l # 目录下有多少项 cat *.py | wc -l # 代码行数
diff -u old.conf new.conf diff -r dir1 dir2 # 比较目录 diff <(sort a) <(sort b) # 比较排序后的内容
| -u | 统一格式 |
| -r | 递归比较目录 |
| -q | 只报告是否不同 |
| -w | 忽略空白 |
| -i | 忽略大小写 |
cmp a.bin b.bin
nl -ba script.sh # 空行也编号
tac app.log | less
strings app.bin | grep -i version
xxd file.bin | head -20 xxd -r dump.txt > file.bin # 还原
nano /etc/hosts # Ctrl+O 保存 Ctrl+X 退出 Ctrl+W 搜索 Ctrl+K 剪切行
vim app.conf # :wq 保存退出 :q! 不保存退出 /词 搜索 dd 删行 u 撤销 :set nu 行号
make 2>&1 | tee build.log echo "text" | sudo tee /etc/file # 用 sudo 写受保护文件 cmd | tee -a log.txt # 追加
ls > list.txt echo "line" >> notes.txt cmd > out.log 2>&1 # 全部进日志 cmd 2>/dev/null # 丢掉错误 cmd &> all.log # bash 简写
ps aux | grep nginx cat log | grep ERROR | wc -l history | tail -20
grep -rn "TODO" src/
grep -i error app.log
grep -v "^#" nginx.conf | grep -v "^$" # 去掉注释与空行
grep -E "5[0-9]{2}" access.log # 扩展正则
grep -l "main" *.c # 只列文件名
grep -A3 -B1 "Exception" app.log # 前 1 后 3 行上下文| -r / -R | 递归目录 |
| -n | 显示行号 |
| -i | 忽略大小写 |
| -v | 反选(不含模式的行) |
| -E | 扩展正则(同 egrep) |
| -F | 当作固定字符串 |
| -w | 整词匹配 |
| -c | 只数行数 |
| -l | 只列匹配的文件名 |
| -o | 只输出匹配部分 |
| -A/-B/-C N | 后 / 前 / 前后 N 行上下文 |
| --include="*.js" | 递归时限制文件名 |
rg "TODO" --type ts
rg -n "fetch\(" src/sed 's/foo/bar/g' a.txt # 输出替换结果 sed -i 's/foo/bar/g' a.txt # 直接修改文件(GNU) sed -i.bak 's/8080/80/' app.conf # 改前留备份 sed 's#/usr/local#/opt#g' f # 分隔符可换
| -i | 就地修改(macOS 需 -i '') |
| -n | 只打印被 p 命令选中的行 |
| -e | 多个脚本 |
| -E | 扩展正则 |
| g 标志 | 一行内全部替换 |
sed -n '10,20p' app.log # 第 10–20 行 sed '5d' f.txt # 删第 5 行 sed '/^$/d' f.txt # 删空行 sed '3i\新的一行' f.txt # 第 3 行前插入
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head # 访问最多的 IP
awk -F: '{print $1}' /etc/passwd # 用户名
awk '$3 > 100 {print $0}' data.txt # 第三列大于 100 的行
awk '{sum += $2} END {print sum}' f # 求和| -F <分隔符> | 字段分隔符(默认空白) |
| $0 / $1 / $NF | 整行 / 第 1 列 / 最后一列 |
| NR | 当前行号 |
| BEGIN{} / END{} | 开始前 / 结束后执行 |
| /正则/ {…} | 只处理匹配的行 |
cut -d, -f1,3 data.csv cut -d: -f1 /etc/passwd cut -c1-8 file # 按字符位置
sort names.txt sort -n nums.txt # 按数值 sort -k2 -t, -r data.csv # 按第 2 列倒序 sort -u list.txt # 排序并去重 sort -h sizes.txt # 按 K/M/G 大小
| -n | 按数值 |
| -r | 倒序 |
| -k N | 按第 N 列 |
| -t <分隔符> | 列分隔符 |
| -u | 去重 |
| -h | 人类可读大小 |
| -V | 版本号排序(1.2 < 1.10) |
sort words.txt | uniq -c | sort -rn sort a.txt | uniq -d # 只显示重复的 sort a.txt | uniq -u # 只显示唯一的
echo hello | tr a-z A-Z # HELLO tr -d '\r' < win.txt > unix.txt # 去掉 CR tr -s ' ' < f # 压缩连续空格 echo $PATH | tr ':' '\n' # 一行一个
find . -name "*.log" | xargs rm
find . -name "*.txt" -print0 | xargs -0 wc -l # 文件名含空格
cat urls.txt | xargs -n1 -P4 curl -sO # 4 路并行
echo a b c | xargs -I{} echo "item: {}"| -0 | 以 NUL 分隔(配 find -print0) |
| -n N | 每次传 N 个参数 |
| -I {} | 用 {} 占位 |
| -P N | N 个并行 |
| -r | 输入为空时不执行 |
paste -d, names.txt emails.txt
join -t, -1 1 -2 1 <(sort a.csv) <(sort b.csv)
cat /etc/fstab | column -t mount | column -t
echo abc | rev # cba
fold -w 80 -s long.txt # -s 在空格处折
iconv -f GBK -t UTF-8 gbk.txt > utf8.txt iconv -l | grep -i gb # 列出支持的编码
dos2unix script.sh sed -i "s/\r$//" script.sh # 没装 dos2unix 时
curl -s https://api.github.com/repos/git/git | jq .stargazers_count jq ".items[] | .name" data.json jq -r ".[].id" list.json # -r 原始字符串不带引号 cat a.json | jq . # 格式化
echo "Hello" echo -e "a\tb\nc" echo $HOME echo "PATH=$PATH" >> ~/.bashrc
printf "%-10s %5d\n" name 42 printf "%.2f\n" 3.14159 printf "%s\n" *.txt # 一行一个文件名
seq 1 10 seq 0 5 100 # 步长 5 for i in $(seq 1 3); do echo $i; done
echo "2^10" | bc echo "scale=3; 10/3" | bc echo "obase=16; 255" | bc # 转十六进制
chmod 755 script.sh # rwxr-xr-x chmod 644 file.txt # rw-r--r-- chmod 600 ~/.ssh/id_ed25519 # 只有自己可读写 chmod -R 755 public/ # 递归
| 755 | 目录 / 可执行文件的常见值 |
| 644 | 普通文件常见值 |
| 600 | 私钥、密码文件 |
| 700 | 私有目录(如 ~/.ssh) |
| -R | 递归 |
chmod +x deploy.sh # 加可执行 chmod u+w,go-w file # 所有者可写、其他不可写 chmod a-x file chmod g+s shared/ # 目录 setgid:新文件继承组
sudo chown www-data:www-data -R /var/www/site sudo chown $USER file.txt chgrp developers project/ # 只改组
umask umask 027 # 组只读、其他无权限
sudo apt update sudo -i # 切到 root 交互 shell sudo -u postgres psql # 以其他用户执行 sudo !! # 用 sudo 重跑上一条
su - deploy exit # 回来
whoami id id deploy # 看别的用户
sudo useradd -m -s /bin/bash deploy sudo passwd deploy sudo usermod -aG sudo deploy # 加入 sudo 组
sudo usermod -aG docker $USER newgrp docker # 或重新登录生效
sudo userdel -r olduser
passwd sudo passwd deploy sudo passwd -l deploy # 锁定账号
groups groups www-data cat /etc/group | grep docker
who w last -n 10 lastlog
ssh-keygen -t ed25519 -C "me@example.com" cat ~/.ssh/id_ed25519.pub ssh-copy-id user@host # 把公钥装到服务器
ssh user@1.2.3.4 ssh -p 2222 user@host # 指定端口 ssh -i ~/.ssh/key.pem ubuntu@host ssh -L 8080:localhost:80 user@host # 端口转发 ssh user@host "uptime" # 只执行一条命令
| -p | 端口 |
| -i | 私钥文件 |
| -L 本地:目标:端口 | 本地端口转发 |
| -N | 只转发不开 shell |
| -v | 调试连接问题 |
Host prod
HostName 1.2.3.4
User deploy
Port 2222
IdentityFile ~/.ssh/prod_keyps aux | grep nginx ps -ef | grep java ps aux --sort=-%mem | head # 最吃内存的 ps -p 1234 -o pid,etime,cmd # 某进程运行了多久
| aux | BSD 风格:所有用户、含无终端、详细 |
| -ef | UNIX 风格:全部进程含父进程 |
| --sort=-%cpu | 按 CPU 倒序 |
| -p PID | 指定进程 |
| -o 字段 | 自定义列 |
pgrep -f "node server.js" pgrep -l nginx # 带名字 pkill -f "node server.js" # 找到并杀
top top -o %MEM top -p 1234 # 只看某进程
htop htop -u www-data
kill 1234 kill -9 1234 # 不听话就强杀 kill -HUP 1234 # 让服务重载配置 kill -l # 信号列表
| -15 / -TERM | 默认:请求正常退出 |
| -9 / -KILL | 强制结束,不给清理机会 |
| -1 / -HUP | 常用于重载配置 |
| -2 / -INT | 等于 Ctrl+C |
| -STOP / -CONT | 暂停 / 继续 |
killall node killall -9 chrome
npm run build & jobs fg %1 # Ctrl+Z 暂停当前前台任务,再 bg 让它后台继续
nohup python server.py > server.log 2>&1 & echo $! # 刚启动的 PID
tmux new -s work # Ctrl+B 然后 d 分离 tmux ls tmux attach -t work tmux kill-session -t work
systemctl status nginx systemctl status --failed # 失败的服务
sudo systemctl restart nginx sudo systemctl reload nginx # 不中断连接重载配置
sudo systemctl enable --now docker sudo systemctl disable apache2 systemctl is-enabled nginx
systemctl list-units --type=service --state=running systemctl list-unit-files | grep enabled
journalctl -u nginx -f journalctl -u app -n 200 --no-pager journalctl --since "1 hour ago" journalctl -p err -b # 本次开机以来的错误 sudo journalctl --vacuum-size=500M # 清理
| -u <单元> | 某服务 |
| -f | 跟随 |
| -n N | 最近 N 行 |
| --since / --until | 时间范围 |
| -p err | 按级别过滤 |
| -b | 本次启动 |
| -k | 内核消息 |
crontab -e # 每天 3:30 备份 30 3 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1 # 每 5 分钟 */5 * * * * /usr/bin/curl -s https://example.com/ping crontab -l # 查看
echo "systemctl restart app" | at 03:00 atq # 队列 atrm 3 # 删除
watch -n 2 "df -h" watch -d free -m # -d 高亮变化
time ./build.sh time curl -s https://example.com > /dev/null
timeout 10 ping example.com timeout -s KILL 30 ./stuck.sh
lsof -p 1234 lsof +D /var/log # 谁在用这个目录的文件 lsof | grep deleted # 已删除但被占用的文件(磁盘不释放)
strace -p 1234 strace -f -e trace=network node app.js strace -c ./cmd # 统计
nice -n 19 tar czf big.tgz data/ renice -n 10 -p 1234
ss -tulnp ss -tlnp | grep :80 ss -s # 连接统计 ss -tan state established
| -t / -u | TCP / UDP |
| -l | 只看监听 |
| -n | 数字端口不解析服务名 |
| -p | 显示进程(需 root 看全部) |
| -a | 全部连接 |
netstat -tulnp | grep 3000 netstat -an | grep ESTABLISHED | wc -l
lsof -i :8080 lsof -i tcp -sTCP:LISTEN kill -9 $(lsof -t -i :3000) # 直接杀掉占用者
ip addr ip -4 -br addr # 精简 hostname -I # 只要 IP
ip route ip route get 8.8.8.8 # 去某地址走哪条路
ping -c 4 example.com ping -i 0.2 -c 20 10.0.0.1
traceroute example.com mtr -rw example.com
curl -I https://example.com # 只看响应头
curl -sS https://api.example.com/x | jq . # 静默但报错
curl -o file.zip -L https://…/file.zip # 下载并跟随重定向
curl -X POST -H "Content-Type: application/json" -d '{"a":1}' https://api.example.com/items
curl -u user:pass https://…
curl -w "%{http_code} %{time_total}\n" -o /dev/null -s https://example.com| -I | 只请求头(HEAD) |
| -L | 跟随重定向 |
| -o 文件 / -O | 保存到文件 / 用远程文件名 |
| -X 方法 | 请求方法 |
| -H "头: 值" | 请求头 |
| -d 数据 | 请求体(默认 POST) |
| -s / -S | 静默 / 静默但显示错误 |
| -v | 显示完整交互 |
| -k | 忽略证书错误(调试用) |
| -w 格式 | 输出状态码、耗时等 |
wget https://example.com/file.tar.gz wget -c https://…/big.iso # 续传 wget -qO- https://example.com | head # 输出到屏幕 wget -r -np -nH --cut-dirs=1 https://example.com/docs/
dig example.com dig +short example.com dig MX example.com dig @8.8.8.8 example.com # 指定 DNS dig -x 93.184.216.34 # 反查
nslookup example.com nslookup -type=txt example.com
host example.com
sudo nano /etc/hosts 127.0.0.1 dev.example.com
nc -zv example.com 443 nc -l 8080 # 监听 8080 echo "hi" | nc host 8080 # 发数据
telnet smtp.example.com 25
sudo ufw status sudo ufw allow 22 sudo ufw allow 80/tcp sudo ufw allow from 10.0.0.0/8 to any port 5432 sudo ufw enable
开启前务必先放行 22,否则 SSH 会被自己关在外面。
sudo firewall-cmd --list-all sudo firewall-cmd --add-port=8080/tcp --permanent sudo firewall-cmd --reload
sudo iptables -L -n -v --line-numbers sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
sudo tcpdump -i eth0 port 80 -nn sudo tcpdump -i any host 10.0.0.5 -w cap.pcap # 存文件给 Wireshark
sudo iftop -i eth0 nload
ip neigh arp -a
tar -czvf site.tar.gz site/ tar -czf logs.tgz --exclude="*.tmp" logs/ tar -cJvf site.tar.xz site/ # xz 压得更小更慢
| -c | 创建 |
| -x | 解开 |
| -t | 列出内容 |
| -z / -j / -J | gzip / bzip2 / xz |
| -v | 显示文件 |
| -f 文件 | 归档文件名(必须紧跟文件名) |
| -C 目录 | 切换到目录再操作 |
| --exclude=PAT | 排除 |
tar -xzvf site.tar.gz tar -xzvf site.tar.gz -C /var/www/ tar -xf any.tar.* # 新版 tar 自动识别压缩格式 tar -tzvf site.tar.gz # 先看看里面有什么
gzip big.log # 得到 big.log.gz gzip -k big.log # 保留原文件 gunzip big.log.gz zcat big.log.gz | grep ERROR # 不解压直接看
zip -r project.zip project/ -x "*/node_modules/*" zip -e secret.zip file.txt # 加密
unzip archive.zip unzip archive.zip -d out/ unzip -l archive.zip # 只看列表 unzip -O gbk cn.zip # Windows 中文文件名乱码时
7z x archive.7z 7z a -mx9 out.7z dir/ 7z x file.rar
xz -9 big.sql xz -d big.sql.xz bzip2 -k file
split -b 100M big.iso part_ cat part_* > big.iso
sha256sum ubuntu.iso sha256sum -c SHA256SUMS md5sum file.zip
sudo dd if=ubuntu.iso of=/dev/sdX bs=4M status=progress && sync dd if=/dev/zero of=test.bin bs=1M count=100 # 100MB 测试文件
of= 写错设备会直接抹掉磁盘,执行前 lsblk 三次确认。
uname -a uname -m # x86_64 / aarch64 cat /etc/os-release # 发行版
hostnamectl sudo hostnamectl set-hostname web-01
uptime # 负载 > CPU 核数(nproc)说明在排队
free -h free -m -s 2 # 每 2 秒刷新
nproc lscpu | grep -E "Model name|^CPU\(s\)"
lsblk lsblk -f # 带文件系统与 UUID sudo fdisk -l
sudo mount /dev/sdb1 /mnt/usb sudo umount /mnt/usb mount | column -t # 已挂载 cat /etc/fstab # 开机自动挂载
vmstat 1 10
iostat -x 1 5
sudo dmesg -T | tail -50 sudo dmesg -T | grep -i "killed process" # 谁被 OOM 了
env | sort printenv HOME echo $PATH | tr ":" "\n"
export JAVA_HOME=/usr/lib/jvm/java-17 export PATH="$HOME/.local/bin:$PATH" echo 'export EDITOR=vim' >> ~/.bashrc && source ~/.bashrc
alias ll="ls -alF" alias gs="git status" unalias ll alias # 列出
history | grep ssh !105 sudo !! history -c # 清空
sudo apt update && sudo apt upgrade sudo apt install htop apt search nginx apt show nginx sudo apt remove --purge pkg && sudo apt autoremove
| update | 刷新软件源索引 |
| upgrade | 升级已装包 |
| install / remove | 安装 / 卸载 |
| search / show | 搜索 / 详情 |
| autoremove | 清理不再需要的依赖 |
| list --installed | 已安装列表 |
sudo dnf install -y git sudo dnf update dnf search nginx sudo yum install epel-release # 老系统
sudo pacman -Syu sudo pacman -S neovim pacman -Ss keyword sudo pacman -Rns pkg
brew install jq brew upgrade brew list brew search ripgrep
sudo snap install code --classic snap list
sudo dpkg -i app.deb sudo apt -f install dpkg -l | grep nginx dpkg -L nginx # 包装了哪些文件
sudo shutdown -h now sudo reboot sudo shutdown -r +10 "10 分钟后重启维护" sudo shutdown -c # 取消
date date "+%Y-%m-%d %H:%M:%S" date -d "yesterday" +%F date +%s # 时间戳 date -d @1700000000 # 时间戳转日期
timedatectl sudo timedatectl set-timezone Asia/Shanghai timedatectl list-timezones | grep Asia
cal cal 2026 cal -3 # 前后各一月
lsmod | grep nvidia sudo modprobe br_netfilter
lspci | grep -i vga lsusb
ulimit -n ulimit -n 65535 # 当前会话 cat /proc/sys/fs/file-max
chsh -s $(which zsh) echo $SHELL
source ~/.bashrc . ~/.zshrc # 同义
#!/usr/bin/env bash set -euo pipefail # 出错即停、未定义变量报错、管道错误传递 for f in *.log; do echo "处理 $f" done
man tar man 5 crontab # 第 5 节:文件格式 tar --help | less tldr tar # 社区示例版(需安装)
A small in-memory filesystem and shell interpreter: it supports ls / cd / cat / grep / sed / awk / find / chmod / tar and more than 60 other commands, with pipes, redirection and wildcards; 8 stages run from "build a directory tree" to "counting with pipes". Nothing goes online and your real files are never touched. Git practice is inthe Git command reference.