简介:这是一份面向Linux初学者、运维人员与开发者的Ubuntu命令速查手册,以PDF文档形式梳理Ubuntu系统下高频使用的命令行操作,适合入门自学、日常查阅以及服务器维护时快速参考。压缩包内共1个PDF文件,体积约6.28MB,内容围绕软件包管理展开,涵盖安装升级、查看软件安装内容、查找软件库、统计安装包信息、查询依赖关系、增加光盘源与系统升级等模块,并介绍Ubuntu技术论坛和中文社区的求助渠道。文档节选显示全书约65页,目录另含前言、Ubuntu概述与Ubuntu承诺等基础章节,同时给出sudo apt-get install、dpkg -L、apt-cache、dpkg --get-selections等命令示例,可帮助读者在安装软件、排查依赖、清理残留配置时按需定位用法。资源已有821人学习下载,适合希望系统熟悉Ubuntu命令与包管理流程的读者收藏备用。
1. 65 页《Ubuntu 命令大全》为什么值得放在手边
很多人装完 Ubuntu,第一件事是把图形界面的设置项翻一遍,第二件事就是在终端里打开一份「命令大全」的 PDF。原因很直白:apt 报依赖断裂、磁盘莫名其妙满了、22 端口被别的进程占着导致远程连不上、内核模块没加载——这些问题在图形界面里根本找不到入口。这份《Ubuntu 命令技巧手册》共 65 页,按安装升级、系统管理、进程管理、网络管理分块,基本覆盖了日常运维中出现频率最高的那批命令。它不讲解内核原理,也不追求命令的完整覆盖,胜在每条命令都对应一个具体场景,抄下来就能用。刚接触 Linux 的人可以当字典按需查,做了几年服务器的人更适合拿它做一次查漏补缺,尤其是 dpkg 与 apt 的查询链条、lsof 定位端口、du 与 df 的配合这几块,翻一遍往往能发现自己一直在用笨办法。
2. apt 与 dpkg:包管理链路的查询、安装与清理
Ubuntu 的包管理体系分成两层:底层是 dpkg,管的是「本机已经装了什么」;上层是 apt,管的是「软件源里有什么、能不能装、依赖怎么解」。搞混这两层,是新手最常见的时间黑洞——比如拿 apt-cache 去查一个已安装文件属于哪个包,怎么查都查不到。下面按查询、安装、清理三段来拆。
2.1 四条查询链路:dpkg、apt-cache、apt-file、apt list
先建立一张对应关系表,知道问题该交给谁。
| 想知道什么 | 命令 | 适用范围 |
|---|---|---|
| 某个文件来自哪个包 | dpkg -S /usr/bin/lsof | 仅已安装包 |
| 某个包装了哪些文件 | dpkg -L openssh-server | 仅已安装包 |
| 软件源里有哪些相关包 | apt-cache search nginx | 名称与描述 |
| 源里全部可用包名 | apt-cache pkgnames | 输出量大,配合 grep |
| 包的版本、大小、依赖 | apt-cache show nginx | 可列出多个版本 |
| 谁依赖了这个包 | apt-cache rdepends --installed openssh-server | 卸载前必查 |
| 缺失的头文件来自哪个包 | apt-file search zlib.h | 需要先apt-file update |
把这几条串起来用,效率比一条条试高得多:
# 1) 文件反查包:先定位可执行文件的真实路径,再反查来源 dpkg -S "$(command -v lsof)" # 输出形如 lsof: /usr/bin/lsof # 2) 列出包内所有配置文件,确认默认路径在哪 dpkg -L nginx | grep -E '\.conf$' # 3) 卸载前的牵连检查:正向依赖 + 反向依赖都要看 apt-cache depends nginx apt-cache rdepends --installed openssh-server # 4) 导出已安装清单,作为迁移或重装的基线 dpkg --get-selections > /root/pkg-$(date +%F).listdpkg -S接收的是文件路径而不是命令名,所以习惯上先command -v取绝对路径再传进去,能避免 shell 别名和 hash 缓存带来的误判。dpkg -L输出的是安装时记录的文件清单,如果你手动往/etc/nginx/conf.d里加过文件,它不会出现在结果里。apt-cache rdepends加不加--installed差别很大:不加会把源里所有可能依赖它的包都列出来,加了这个参数才只看本机实际情况,删包前用后者更准。
2.2 安装与升级:apt-get 的参数、修依赖与源
apt-get 出问题,九成集中在三个地方:索引过期、依赖断裂、源配置异常。对应三条命令就能解决大半。
sudo apt-get update # 只刷新索引,不装任何东西 sudo apt-get install -y nginx # -y 免交互,脚本里必加 sudo apt-get -f install # 修复上次中断留下的依赖断裂 sudo apt-get install --reinstall nginx # 配置文件被改乱后原样复原 sudo apt-get build-dep python3-numpy # 拉齐编译期依赖,解决缺 h 文件-f是--fix-broken的缩写,作用是「把系统里现在不一致的依赖关系补齐」,它本身不指定包名,属于兜底动作。编译时提示找不到某类头文件,比较稳妥的做法是先用apt-file search定位提供该头文件的包,再决定装-dev包还是直接build-dep整个源码包的依赖树。
源相关的两个动作也值得记住。增加本地光盘源时,如果不想手工编辑/etc/apt/sources.list,可以用sudo apt-cdrom add让系统自动识别并追加。至于第三方源,早期教程里常见的apt-key adv --recv-keys在新版本中已经不再推荐,取而代之的是把公钥文件直接放到/etc/apt/trusted.gpg.d/目录,或者在源条目里用signed-by=指定密钥路径——后者粒度更细,一个源对应一把钥匙,出问题时容易定位。
2.3 缓存清理、孤立包与清单恢复
磁盘告警时,/var/cache/apt/archives是被低估的占用大户,同时也有必要顺手清理不再使用的孤立软件包:
sudo apt-get autoclean # 只清掉源里已下架的旧版本包 sudo apt-get clean # 清空整个 archives 目录 sudo apt-get autoremove --purge # 连残留配置文件一起删 deborphan | xargs -r sudo apt-get -y purge # 清理无人依赖的孤儿库autoclean和clean的区别在于前者会保留仍可用版本的包,方便你离线重装;后者彻底清空,释放空间更猛。--purge的作用是把软件包状态标记为「完全移除」,避免配置文件长期占着/etc而不被察觉。deborphan不在默认安装里,需要先通过 apt 装上,它输出的包名建议先人工过一遍再批量 purge,因为部分运行时插件本身就是「没人显式依赖」的形态。
迁移场景下还有一招很好用——先拿到包的下载地址,再到无外网环境里用 dpkg 装:
apt-get --print-uris install nginx | grep -E "^'http" # 按输出把 .deb 拷过去,然后 dpkg -i 逐个安装恢复包清单时注意,dpkg --set-selections只改状态不装包,真正触发安装的是后一条命令,而且执行前一定要用-s走一遍模拟:
sudo dpkg --set-selections < /root/pkg-2024-06-01.list sudo apt-get -s dselect-upgrade | less # -s 只模拟,确认无误再执行 sudo apt-get dselect-upgrade注意:
dselect-upgrade会按清单做增减。源里找不到同名包时它不会报错,只是静默跳过,事后必须再导一次dpkg --get-selections和基线对账。
3. 内核、硬件与磁盘:从系统信息到分区挂载
系统管理这块命令多而杂,但可以按「先看是谁、再看有什么、最后看怎么挂」三层来记忆。顺序对了,排查时就不会东一榔头西一棒子。
3.1 内核、发行版与硬件探针
| 目标 | 命令 | 备注 |
|---|---|---|
| 内核版本 | uname -r | 装驱动、编译模块前先确认 |
| 发行版与代号 | lsb_release -a | 精简镜像可能没有,回退/etc/os-release |
| 已加载模块 | lsmod | 配合modprobe增删 |
| PCI 设备树 | lspci -tv | -t树形,-v详细 |
| USB 设备树 | lsusb -tv | 排查 U 盘识别异常 |
| CPU 概要 | lscpu | 比读/proc/cpuinfo直观 |
| 整机序列号 | dmidecode -s system-serial-number | 需要 root |
| 开机时长与负载 | uptime | 负载三项分别是 1/5/15 分钟均值 |
| 硬盘温度 | smartctl -A /dev/sda | 需先装 smartmontools |
uname -r lsb_release -a 2>/dev/null || grep PRETTY_NAME /etc/os-release lscpu | grep -E 'Model name|^CPU\(s\)|MHz' # 型号、核数、主频 free -m # 以 MB 为单位看内存 sudo dmidecode -s system-serial-number # 报修、资产登记常用lsb_release依赖 lsb-release 这个包,容器镜像和裁剪过的系统上经常没装,所以脚本里最好写成上面这种「拿不到就退回读/etc/os-release」的写法。lspci -tv的树形输出能直观看出哪些设备挂在哪个桥下面,排查一块网卡为什么没起来时,比翻 dmesg 更快定位。DMI 信息属于硬件层,虚拟机里读出来的多是宿主平台统一的字符串,做资产唯一性标识时要注意这个坑。
3.2 分区、格式化与挂载
lsblk -f # 一眼看清盘、分区、文件系统、UUID sudo fdisk -l # 传统视角,看分区表类型与起始扇区 sudo mkfs.ext4 -L data /dev/sdb1 # -L 打卷标,便于按 LABEL 挂载 sudo fsck -y /dev/sdb1 # 指定分区必须处于未挂载状态 sudo mount -o loop ubuntu.iso /mnt/iso sudo mount -t ntfs-3g -o rw,uid=1000,gid=1000 /dev/sda2 /mnt/win sudo mount -t vfat -o iocharset=utf8,umask=022 /dev/sdb1 /mnt/usbmkfs.ext4会重建文件系统结构,执行前务必用lsblk确认设备名。fsck在已挂载分区上跑,轻则拒绝执行,重则损伤数据,先umount是铁律。挂载 ISO 靠的是 loop 设备,-o loop让内核把普通文件当块设备处理,这在离线装包时非常实用。NTFS 分区要可写,必须走 ntfs-3g,只读需求则用内核自带的-t ntfs -o ro更省事;uid、gid决定挂载后文件归属谁,不指定的话普通用户只能看不能写。FAT32 的iocharset=utf8解决中文文件名显示为问号的问题,umask控制默认权限位。
要长期生效,写进/etc/fstab,用 UUID 而不是/dev/sdX,因为设备名会随插拔顺序变化:
sudo blkid /dev/sdb1 # 先取 UUID # 追加到 /etc/fstab,格式为:设备 挂载点 类型 选项 dump fsck顺序 UUID=1a2b-3c4d /data ext4 defaults,noatime 0 2noatime省掉每次读文件都更新访问时间的写操作,对读写频繁的目录收益明显。最后两列中,第一个是 dump 备份标志,几乎永远填 0;第二个是开机自检顺序,根分区填 1,其他分区填 2,不需要自检的填 0。
3.3 df 与 du:空间排查的两把尺子
这两个命令得出的结论经常对不上,理解差异就理解了大半磁盘故障。
df -hT -x tmpfs -x devtmpfs # 看挂载点剩余;-T 显类型,-x 排除伪文件系统 df -i # 看 inode 使用率,小文件多时最先耗尽 du -sh /var/* 2>/dev/null | sort -rh | head -n 10 lsof +L1 2>/dev/null | head # 揪出句柄未释放的已删除文件df读的是文件系统超级块,du是逐个文件累加,两者差出几个 G,通常意味着有进程还开着已被删除的文件句柄——日志轮转脚本删了文件但服务没重开,就会是这种表现。df -i尤其容易被忽略:磁盘还有空间但写不进去,一查 inode 已经 100%,原因是目录里堆了海量小文件,此时清理小文件比删大文件有效。
卸载时提示target is busy,同样用这套工具定位:
lsof +f -- /mnt/usb # 列出占着该挂载点的进程 sudo fuser -vm /mnt/usb # 另一条等价思路 sudo umount -l /mnt/usb # 确认无写入后再惰性卸载提示:
umount -l只是把挂载点从命名空间里摘掉,真正释放要等占用进程退出,数据还在持续写入时强上这一条,有丢数据的风险。
4. 进程、端口与句柄:故障现场的三板斧
服务器出问题,能稳定复用的排查顺序是:谁在占资源 → 谁在占端口 → 谁在占文件。这三步分别对应进程列表、套接字列表和 lsof,覆盖了大部分「服务起不来」「远程连不上」「磁盘删不掉」的场景。
4.1 进程快照与排序
ps aux --sort=-%mem | head -n 6 # 内存占用前五 ps -eo pid,ppid,user,%cpu,%mem,rss,etime,comm --sort=-%cpu | head top -b -n1 -o %CPU | head -n 12 # -b 批处理,-n1 只刷一次 pstree -p 1234 # 看某个进程的子进程树 w # 当前登录用户及其正在跑的命令ps aux输出里RSS是常驻内存,单位 KB,判断一个 php-fpm 进程是否吃太多内存看它比看%MEM准。etime是进程已运行时长,配合ppid能快速识别「反复被拉起又秒退」的守护进程——如果同一命令名的进程 etime 都是几秒,说明有东西在循环重启它,此时该去翻日志而不是继续 kill。top -b -n1适合塞进脚本,因为它输出完就退出,不会像交互模式那样一直占着终端。
按内存排序时,--sort后面跟的字段名前面加-表示降序,这一点和sort -rh的写法不同,容易写反。
4.2 端口与文件句柄:lsof 和 ss 的组合
SSH 连不上,第一步不是看防火墙,而是确认 22 端口到底有没有进程在听:
sudo ss -tunlp | grep :22 # t/u 是 TCP/UDP,n 不做反解,l 只听,p 带进程 sudo lsof -i:22 # 输出更啰嗦但能看到连接状态lsof 的表达能力比多数人以为的强,记住几种常用写法就够日常用:
| 写法 | 含义 |
|---|---|
lsof -i:8080 | 按端口过滤 |
lsof -u www-data | 按用户过滤 |
lsof -p 1234 | 按进程号过滤 |
lsof /var/log/syslog | 按文件路径过滤 |
lsof +D /tmp | 递归整个目录 |
lsof -c nginx | 按进程名过滤 |
排查配置热加载失败时,lsof -p <PID> \| grep REG能看出进程实际打开的是哪个配置文件,很多「改了不生效」的问题到这里就水落石出了——改的是/etc/app/conf.d/a.conf,进程读的却是打包时写死的另一份。找出被占用的目录则用fuser -vm /data,它和lsof +D思路一致,但输出更紧凑,适合写进判断分支。
4.3 后台运行、ulimit 与僵死进程
长任务放后台,最省事的组合是 nohup 加重定向:
nohup ./worker.sh > worker.log 2>&1 & disown -h %1 # 从作业表摘掉,避免退出 shell 时收到信号带交互的程序 nohup 救不了,得用 screen 或 tmux,断开后重新 attach 就能接着看输出。想让进程完全脱离当前会话,可以用setsid,它会新建一个会话并把进程放进去,同时记得把标准输入也重定向掉,否则进程仍可能因为读到 EOF 而退出。
句柄上限是另一类隐蔽故障。服务报too many open files,按会话临时改和按用户永久改是两条路径:
ulimit -n # 查看当前会话上限 ulimit -n 65535 # 临时提高,只对本 shell 及子进程生效 sudo tee -a /etc/security/limits.conf <<'EOF' * soft nofile 65535 * hard nofile 65535 EOF软限制是进程自己可以调高的上限,硬限制是天花板,普通用户不能突破硬限制。这两条对通过 PAM 登录的会话有效,但 systemd 托管的服务不受其约束,得在 unit 文件里写LimitNOFILE=65535,这是很多人改完 limits.conf 发现「没生效」的真正原因。
僵死进程看着吓人,处理逻辑却很简单:
ps -eo pid,ppid,stat,comm | awk '$3 ~ /^Z/'状态为 Z 的进程已经结束,只是父进程还没调用 wait 回收,所以kill -9对它无效。正确做法是找到对应的 PPID,处理父进程——重启父进程或者让它重新 wait,之后由 init 接管回收。批量清理超规格进程时,用--no-headers去掉表头,避免 awk 把字段名当数据:
ps -eo pid,rss,comm --no-headers \ | awk '$3=="php-cgi" && $2>122880 {print $1}' \ | xargs -r kill122880是 KB,等于 120 MB;xargs -r在没有输入时不执行命令,防止kill空跑报错。
5. 把 65 页命令压成一个可落地的巡检脚本
手册里的命令大多是单点的,真正省时间的做法是把它们串成一次巡检,每天定时输出一份快照。下面这个脚本覆盖发行版、磁盘、inode、内存、高占用进程和监听端口六项,跑完直接看日志:
#!/usr/bin/env bash # ubuntu-checkup.sh —— 日常巡检,输出重定向到日志即可 set -uo pipefail # 故意不加 -e,单项失败也要继续跑完 echo "== 发行版 / 内核 ==" /usr/bin/lsb_release -ds 2>/dev/null || /usr/bin/grep PRETTY_NAME /etc/os-release /usr/bin/uname -r echo "== 磁盘 ==" /usr/bin/df -hT -x tmpfs -x devtmpfs -x overlay echo "== inode 使用率超过 80% 的挂载点 ==" /usr/bin/df -i | awk 'NR==1 || $5+0 > 80' echo "== 内存 ==" /usr/bin/free -m echo "== CPU 占用前 5 的进程 ==" /usr/bin/ps -eo pid,ppid,%cpu,%mem,rss,comm --sort=-%cpu | head -n 6 echo "== 监听端口 ==" /usr/sbin/ss -tunlp 2>/dev/null | head -n 20set -uo pipefail里不加-e是有意的:巡检脚本的价值在于把当前状态一次性摊开,任何一项失败都应该继续往下走。命令全部使用绝对路径,是因为 cron 的 PATH 通常只有/usr/bin:/bin,ss偏偏在/usr/sbin下,不写全路径会直接报 command not found——这和很多人遇到的「脚本手动跑正常、扔进定时任务就失效」是同一类问题,多数时候是环境变量差异而不是脚本本身有错。
df -i那条 awk 的写法值得留意:NR==1保证表头始终输出,$5+0 > 80里的+0把带百分号的字段强制转成数字再比较,否则字符串比较会得出错误结果。同理,脚本里的head -n 6是含表头的行数,不是进程数。
落到定时任务:
# 每天 8 点执行,日志按日期归档;cron 里 % 必须转义 0 8 * * * /opt/checkup/ubuntu-checkup.sh >> /var/log/checkup/$(date +\%F).log 2>&1在 WSL 环境里跑这份脚本要额外注意两点:df会带上自动挂载的 Windows 盘,输出里出现/mnt/c是正常的,想过滤可以在-x后面继续追加对应文件系统类型;ss -tunlp里的-p需要 root 权限才能显示进程名,普通用户跑出来的进程列会是空的,别误判成「没人监听」。
阈值不要照搬 80。先按这个版本跑两周,看 inode 的增长斜率:如果每天涨 0.5% 以上,说明有小文件持续堆积,得回到第 3 章那套du --max-depth的思路逐层定位;如果长期稳定在 60% 以下,把 awk 里的数字调高到 90 也未尝不可。真正有价值的不是脚本本身,而是日志里那条随时间变化的曲线。
本文还有配套的精品资源,点击获取