别再空按上下键:20 个可复现的 Bash 与 GNU coreutils 场景
源微信页常触发验证码拦截。正文不以源文清单为底稿,而以可在本机复现的 Bash 历史展开、作业控制、GNU coreutils、find/xargs 场景重组。每条都给出「什么时候用」和「能跑的命令」——目标不是鸡汤口号,而是让你在 SSH 会话里少敲十遍键盘。
下文命令在常见 Linux(Bash + GNU coreutils)上验证;macOS 若用 BSD 工具,行为可能略有差异,必要时装 coreutils / findutils。

一、先把「历史」当成可检索素材库
多数人只按上下箭头翻命令。Bash 的历史展开(history expansion)和反向搜索,才是真正把「昨天敲过的长命令」变成一键复用。
1. !!:整条重跑上一命令
典型场景:忘了加 sudo,或上一行测通了想立刻再跑一遍。
apt-get update
# Permission denied 之后:
sudo !!
!! 会展开成上一行的完整文本。展开发生在真正执行前,终端通常会先显示展开后的命令。
2. !$ / $_:只复用「上一个参数」
你刚 vim /etc/nginx/nginx.conf,接着想备份或校验同一个路径:
cp !$ ~/nginx.conf.bak
# 或在脚本/管道里更稳妥:
cp $_ ~/nginx.conf.bak
交互式提示符下 !$ 是历史展开;$_ 是特殊变量,脚本里更可移植。用前可先 echo !$ 确认路径无误。
3. Ctrl+R:按片段反向搜索历史
按 Ctrl+R,输入 docker compose 或 kubectl apply 的任意片段,Bash 会从最近往过去匹配;再按一次 Ctrl+R 切到更早命中。回车执行,方向键落到提示符再改。
这是「少按上下键」里收益最大的一条——前提是历史足够长且干净(见第 5 条)。
4. ^旧^新:就地改一字重跑
上一行路径写错了一个目录名:
curl -I https://example.com/heath
# 立刻改成 health:
^heath^health
等价于对上一命令做一次字符串替换后重跑,比箭头键定位再改更快。
5. 调大并去重历史:让 Ctrl+R 真有料
# 写入 ~/.bashrc
export HISTSIZE=50000
export HISTFILESIZE=50000
export HISTCONTROL=ignoredups:erasedups
shopt -s histappend
PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
histappend 避免多终端互踩覆盖;ignoredups:erasedups 减少「同一条 git status 刷屏」。脚本里建议 set +H,关掉历史展开,防止字符串里的 ! 被误展开。
二、作业控制:前台卡住时别重开 SSH
长编译、tail -f、交互式 REPL 占住前台时,作业控制比「再开一个会话」更干净。
6. Ctrl+Z → bg / fg:挂起与切回
# 正在跑的前台任务按 Ctrl+Z 挂起
jobs -l
bg %1 # 后台继续
fg %1 # 再拉回前台
jobs 看编号,%1 指作业 1。适合「临时要执行别的命令,等会儿还要回来」的场景。
7. command & 与 disown
long-job.sh > /tmp/long-job.log 2>&1 &
disown %1
& 启动即后台;disown 后即使关掉终端,作业也不再被 shell 的 SIGHUP 带走(仍受系统与 nohup/systemd 策略影响)。需要持久守护进程时,优先用 systemd / screen / tmux,而不是长期依赖 disown。
8. timeout:给命令加硬截止
timeout 30s curl -fsS https://example.com/health || echo "超时或失败: $?"
退出码 124 通常表示超时(GNU coreutils)。适合健康检查、卡死的网络探测,避免一条命令拖死整个脚本。
三、目录与路径:少打绝对路径
9. cd -:在两个目录间乒乓
cd /var/log/nginx
cd /etc/nginx
cd - # 回到 /var/log/nginx
cd - # 再回到 /etc/nginx
$OLDPWD 保存上一次目录,排障时在「配置目录」和「日志目录」之间跳最省事。
10. pushd / popd / dirs:目录栈
pushd /etc/systemd/system
# ... 改 unit ...
popd
dirs -v
比记一串绝对路径更适合「临时钻进去再原路返回」的排查路径。
11. 花括号展开:一次生成一批名字
mkdir -p backup/{conf,data,logs}
touch report-{2026-09-01..2026-09-03}.md
echo file{1..3}.log
展开发生在执行前,适合批量建目录、按日期占位文件,减少复制粘贴。
四、文本与管道:把日志变成可算的数据

12. tee:一边看屏幕一边落盘
./deploy.sh 2>&1 | tee /tmp/deploy-$(date +%Y%m%d-%H%M%S).log
管道默认只进下游;tee 复制一份到文件,排障时既要实时输出又要留证据时用。
13. cut + sort + uniq -c:快速频次统计
# 假设 access.log 里 IP 在第一列
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head
# 或固定分隔符字段:
echo 'app=api;env=prod;region=cn' | tr ';' '\n' | cut -d= -f1
不必一上来写复杂脚本:先用管道把「谁出现最多」看清楚。
14. grep -n / grep -R:带行号与递归
grep -n 'ERROR' app.log | head
grep -R --include='*.yml' 'image:' deploy/
-n 方便对照编辑器跳转;--include 限制后缀,避免扫进 node_modules。
15. Here-string 与进程替换
grep -E '^(host|port)=' <<< $'host=127.0.0.1\nport=8080'
# 对比两个命令输出,无需临时文件:
diff <(ls dir-a) <(ls dir-b)
<<< 把字符串当 stdin;<(...) 把命令输出伪装成文件路径,适合对比、comm、diff。
五、find / xargs:批量操作别踩空格坑
16. find -print0 | xargs -0:安全处理带空格文件名
find ./logs -name '*.log' -mtime +7 -print0 \
| xargs -0 -r rm -v
默认 xargs 按空白拆词,文件名含空格会炸。-print0 / -0 用 NUL 分隔;-r(GNU)在无输入时不跑命令。
17. xargs -I{}:把参数插到指定位置
printf '%s\n' img1 img2 img3 | xargs -I{} echo "处理: {}.png"
需要「每个参数单独成一条命令」或参数不在末尾时用 -I。
六、磁盘、进程与网络:排障最小工具集

18. du / df / stat:先看清体积与元数据
df -h /
du -h --max-depth=1 /var 2>/dev/null | sort -h | tail
stat -c '%n size=%s mtime=%y' /var/log/syslog
du --max-depth=1 找「哪个子目录在吃盘」;stat 看权限、大小、时间戳,比单纯 ls -l 更可编程。
19. pgrep / pkill / ps:按名定位进程
pgrep -a nginx
ps -o pid,etime,cmd -p "$(pgrep -d, nginx)"
# 谨慎:先 pgrep 确认再 pkill
# pkill -f 'uvicorn.*8000'
先 pgrep -a 看完整命令行,确认无误再杀。生产环境优先用服务管理器的 systemctl stop。

20. ss 与 curl -w:端口与 HTTP 耗时
ss -tlnp | grep ':8080' || true
curl -o /dev/null -s -w 'dns=%{time_namelookup} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
https://example.com/
ss 替代老式 netstat 看监听端口;curl -w 把 DNS/连接/首字节拆开,定位「慢在哪一段」。
七、把技巧固化成习惯(可选练习)
配套脚本 practice/cli_drill.sh 把若干条串成可重复演练:历史相关命令需在交互 Bash 里手敲,脚本侧重 coreutils、超时、空安全 xargs。
bash practice/cli_drill.sh
建议你自己再加三条 alias(写进 ~/.bashrc),只固化你每天真会用的,例如:
alias ll='ls -lah --group-directories-first'
alias g='git'
alias ports='ss -tlnp'
八、边界与安全提醒
历史文件
~/.bash_history可能含密码、Token。共享机器上应避免在命令行明文写密钥;敏感命令可前缀空格并配合HISTCONTROL=ignorespace不入库。
sudo !!、xargs rm、pkill -f都有误伤面。展开或匹配不确定时,先echo/pgrep -a/xargs -n1 echo干跑。BusyBox 精简环境、Alpine、macOS BSD 工具链与 GNU 选项并不完全一致;写进自动化脚本前,在目标镜像里再跑一遍。
小结
把这 20 条按「场景」记,而不是按「背命令」记:
| 卡点 | 先试 |
|---|---|
| 重复敲长命令 | Ctrl+R / !! / !$ / ^旧^新 |
| 前台任务占住终端 | Ctrl+Z + bg/fg,或 timeout |
| 两个目录来回跳 | cd - / pushd |
| 日志要统计、要留档 | tee / sort\|uniq -c / grep -n |
| 批量删改怕空格 | find -print0 \| xargs -0 |
| 盘满、端口、HTTP 慢 | du/df/ss/curl -w |
终端提速不靠「再收藏一篇 600 条命令大全」,而靠把高频路径练成肌肉记忆。把本篇里你本周会用到的 5 条写进 ~/.bashrc 或小脚本,比通读一遍更有用。
💻 配套实训环境与动手练习
本文涉及的相关技术指令、开发环境与工具链已内置在边学边练在线实验室中,无需繁琐安装配置,随时在浏览器中实践体验: