“Ubuntu操作指令及快捷键”这个话题,乍一听像是把官方手册抄一遍就能交差,实际上手之后你会发现,真正拉开效率差距的从来不是记住多少条命令,而是把高频操作压成肌肉记忆之后腾出来的那部分注意力。我在日常开发、服务器运维、给新人做环境搭建的过程中反复验证过一件事:一个熟练的Ubuntu使用者和一个刚入门的使用者,面对同样的任务,差距往往不在“会不会”,而在“手要不要离开主键区”。前者习惯用Ctrl+R翻历史命令、用Super+方向键切窗口、用Tab补全路径,一整套操作行云流水;后者则在鼠标、菜单、终端之间来回横跳,一条命令敲三遍还带拼写错误。这篇文章就是围绕这个差距展开的,把Ubuntu桌面端的快捷键体系和终端里的核心操作指令拆开讲透,从窗口管理、文件操作、权限控制、包管理一直到进程排查和日志定位,配上我自己踩过的坑和实测有效的组合技巧。不管你是刚装完系统还在适应GNOME桌面逻辑的新手,还是已经能写脚本但想再快一档的老用户,下面这些内容都能直接拿去用。
1. 桌面快捷键:先把手指从鼠标上解放出来
1.1 为什么Ubuntu的效率起点是Super键
Ubuntu默认桌面环境是GNOME,而GNOME的交互心脏就是那个画着Windows图标的Super键(有些键盘上印的是Win键,Mac键盘对应Command键)。刚接触的人常常把它当成“打开开始菜单”的按钮,其实它承担的是全局调度中心的角色:按一下弹出活动概览,再按一下收起;按住不放配合其他键可以触发组合动作。理解这一点很关键,因为后面所有的窗口管理、工作区切换、应用启动,全部围绕Super展开。
我个人的使用习惯是把它当作“思维切换器”。写代码写到一半需要查文档,Super敲一下,直接输入应用名首字母回车,比在Dock上找图标快得多;开会时想快速把桌面藏起来,Super+D一步到位;临时离开工位,Super+L锁屏,这个动作我基本已经条件反射了。需要说明的是,不同Ubuntu版本对应的GNOME版本不同,20.04是GNOME 3.36,22.04是GNOME 42,24.04是GNOME 46,快捷键的默认值有一点点差别,比如24.04的截图快捷键改成了PrintScreen直接弹工具条。如果你发现按了没反应,不要在论坛里瞎找,直接在“设置 → 键盘 → 键盘快捷键”里搜一下,那里是最权威的。
提示:如果某天快捷键突然集体失灵,先确认是不是输入法框架抢了按键,再检查
gsettings有没有被某些优化工具改乱。恢复默认值的命令是gsettings reset-recursively org.gnome.desktop.wm.keybindings,执行完注销重进即可。
1.2 高频桌面快捷键清单与实测手感
下面这张表是我自己整理并长期使用的版本,覆盖了90%以上的日常场景。需要强调的是,“手感”这件事因人而异,表里标注的推荐度是我用下来的主观评价,你可以按自己的习惯增删。
| 快捷键 | 作用 | 我的使用频率 | 备注 |
|---|---|---|---|
Super | 打开/关闭活动概览 | 极高 | 输入应用名可直接启动 |
Super+A | 打开应用列表 | 高 | 比翻Dock快 |
Alt+Tab | 切换应用窗口 | 极高 | 按住Alt连按Tab可循环 |
Alt+反引号 | 同一应用的多窗口切换 | 高 | 多个终端时特别好用 |
Super+方向键 | 窗口贴边/最大化/还原 | 极高 | 左半屏右半屏分屏神器 |
Super+Shift+方向键 | 窗口跨显示器移动 | 中 | 双屏必备 |
Super+D | 显示桌面 | 高 | 演示时救场 |
Super+L | 锁定屏幕 | 极高 | 离座必按 |
Super+W | 关闭当前窗口 | 中 | 慎用,容易误关 |
Super+PageUp/PageDown | 切换工作区 | 中 | 配合多桌面使用 |
Super+Shift+PageUp/PageDown | 把当前窗口移到其他工作区 | 低 | 任务分组用 |
Ctrl+Alt+T | 打开终端 | 极高 | 我改成了Super+Enter |
Alt+F2 | 运行命令对话框 | 中 | 临时跑个单条命令很方便 |
Alt+F4 | 关闭窗口 | 高 | 和Windows一致 |
Super+V | 剪贴板历史 | 中 | 需要GNOME 42以上 |
这里重点说两个容易忽略的。第一个是Alt+反引号,也就是数字1左边那个键。很多人开了五六个终端窗口,切换时用Alt+Tab一个个翻,其实同一应用内的多窗口用这个组合一条命令就到位,逻辑上等同于浏览器的标签切换。第二个是工作区,GNOME默认是动态工作区,你打开窗口它自动增加。配合Super+方向键把不同任务的窗口甩到不同工作区,比如第一个工作区放编辑器和终端,第二个放浏览器和文档,第三个放聊天工具,脑子里的上下文切换成本会明显下降。
1.3 终端窗口自身的操作:比快捷键更值钱的是补全
终端是Ubuntu使用者的主战场,但很多人只记住了Ctrl+Shift+C/V复制粘贴,其实GNOME Terminal自带了一整套窗口级快捷操作,用熟了效率提升非常直观。
# 常用终端快捷键(GNOME Terminal) Ctrl+Shift+T # 新建标签页 Ctrl+Shift+W # 关闭当前标签页 Ctrl+PageUp/Down # 左右切换标签页 Ctrl+Shift+N # 新建窗口 Ctrl+Shift+Q # 关闭整个终端(部分版本) Ctrl+Shift+F # 在终端内搜索 Ctrl+L # 清屏,等价于 clear Ctrl+R # 反向搜索历史命令 Ctrl+G # 退出历史搜索真正决定速度的是行编辑组合。Ctrl+A跳到行首、Ctrl+E跳到行尾、Ctrl+U删到行首、Ctrl+K删到行尾、Ctrl+W删掉前一个单词、Alt+Backspace同理但按词删除、Ctrl+Y粘贴刚才删掉的内容。这套东西刚学的时候觉得别扭,用一周之后再让你回去按方向键一个个挪光标,你会难受。
补全方面还有几个进阶用法:连按两次Tab会列出所有候选路径,这个大家都知道;但如果候选太多终端会问你“Display all 1234 possibilities?”,直接按n再补几个字符反而更快。Alt+.或者Alt+_可以粘贴上一条命令的最后一个参数,比如你先ls /var/log/nginx/,接着想cd进去,直接cd Alt+.就完事了,省去重新敲一长串路径。
注意:
Ctrl+S在终端里是流控暂停,不是保存。不小心按到会表现为“终端卡死”,敲什么都没反应,这时候按Ctrl+Q恢复即可。这个坑几乎每个新手都会踩一次。
2. 文件与目录操作:不会出事的写法比写得快更重要
2.1 目录导航:cd的几种姿势和ls的参数取舍
文件系统操作是所有命令的地基,而地基里最常被低估的是路径认知。很多人cd进去之后不知道自己在哪,用pwd确认一下是最朴素的做法,但其实提示符本身就带路径,只是默认配置下只显示最后一级目录。我个人习惯在~/.bashrc里把提示符改成显示完整路径,改法后面章节会说。
cd的几个高频变体值得单独记:cd不带参数回用户主目录,cd -回到上一个目录,这个在兩個目录之间来回跳时极其好用;cd ~也是回主目录,~会被shell展开成/home/你的用户名;cd ..上一级,cd ../..上两级。还有一个冷门但实用的pushd和popd,它们维护一个目录栈,pushd /var/log会把你推进去并把原目录压栈,之后popd就弹回来,处理“临时去某个目录办点事再回来”的场景非常顺手。
ls的参数组合是另一个高频考点。ls -l长格式,能看权限、属主、大小、时间;ls -a显示隐藏文件;ls -h把字节数转成人类可读的 K/M/G;ls -t按修改时间排序,最新的在最前;ls -S按大小排序;ls -r反转顺序。这几个可以叠加,比如ls -lhtr就是“长格式、人类可读、按时间倒序、最旧的在前”,我看日志目录基本就用这个组合。
# 我常用的几个目录操作组合 ls -lhtr # 按时间从旧到新,长格式,人类可读 ls -lah # 包含隐藏文件的全量列表 du -sh * | sort -h # 当前目录下各子项占用空间,从小到大 tree -L 2 # 两层目录树(需要先装 tree) realpath ./config # 把相对路径转成绝对路径realpath这个命令很多人不知道,但它解决了一个很实际的问题:你在软链接目录里工作,pwd显示的是链接路径,可你写脚本时需要一个真实的绝对路径,realpath一敲就出来了。另外ls -i可以看inode号,处理“文件名里有特殊字符删不掉”这类问题时,用inode删除是终极手段。
2.2 复制、移动、删除:三个命令背后的安全边界
cp、mv、rm看起来是最简单的三个命令,但生产环境里出的事故八成和它们有关。先说cp,默认行为是覆盖不提示、不保留属性。cp -r递归复制目录,cp -a归档模式,等价于-dR --preserve=all,会保留权限、时间戳、软链接本身而不是跟随链接,做备份时应该优先用-a而不是-r。cp -u只在源文件比目标新时才复制,做增量同步很实用。cp -p保留属性但不递归,适合单文件。
cp -a /etc/nginx /backup/nginx-$(date +%F) # 带日期备份,保留所有属性 cp -u src/*.conf /etc/app/conf/ # 只复制更新的文件 mv oldname newname # 重命名 mv /data/app /data/app.bak # 移动目录mv有个隐藏细节:跨文件系统移动时,它实际执行的是“复制+删除”,文件很大的话会很慢,而且中途中断可能留下不完整文件。同文件系统内移动只是改目录项,瞬间完成。判断方法是用df看两个路径是否在同一挂载点下。
rm是唯一一个没有回收站的命令,rm -rf更是事故高发区。我踩过最典型的一次坑是写脚本时这样写:
# 危险写法:变量为空时会变成 rm -rf / rm -rf $TARGET_DIR/如果TARGET_DIR因为某种原因没赋值,这条命令实际执行的是rm -rf /。正确做法是加保护,或者用set -u让未定义变量直接报错退出。更稳妥的习惯是把变量写在后面并加引号:
rm -rf "${TARGET_DIR:?变量为空,终止执行}/"${VAR:?message}这个写法在变量为空或未定义时会打印消息并退出,是脚本里的保命符。另一个习惯是删除前先用ls确认一遍匹配范围,尤其是用通配符的时候。rm *.log和rm * .log差一个空格,后者会删掉当前目录所有东西。如果实在怕误删,可以装trash-cli,用trash-put代替rm,文件进回收站,后悔还来得及。
2.3 查找与批量处理:find配合xargs的正确打开方式
find是文件系统里的搜索引擎,也是最容易被用错的命令之一。基本结构是find 路径 条件 动作。常用条件有-name(按文件名,支持通配符)、-iname(忽略大小写)、-type f/d/l(文件/目录/链接)、-size(大小,支持+10M-1k这种写法)、-mtime(修改时间,-7表示7天内,+30表示30天前)、-user(属主)。
# 找出7天内修改过的大于100M的日志文件 find /var/log -type f -name "*.log" -mtime -7 -size +100M # 删除30天前的临时文件(先确认再删) find /tmp -type f -mtime +30 -print find /tmp -type f -mtime +30 -delete # 批量改权限 find /data/www -type d -exec chmod 755 {} \; find /data/www -type f -exec chmod 644 {} \; # 批量查找并统计 find . -name "*.py" -print0 | xargs -0 wc -l | tail -1-exec和xargs的区别值得讲清楚。-exec ... {} \;是对每个匹配项单独执行一次命令,文件多的时候非常慢;-exec ... {} +会把多个文件合并成一次调用,效率高很多。xargs也是合并参数,但默认按空格切分,文件名里有空格就会出错,所以配合find -print0和xargs -0使用是标准做法。
locate是另一个维度的查找,它查的是预建索引数据库,速度极快但可能过时。刚创建的文件locate找不到,需要sudo updatedb刷新。我的习惯是:找已知大致位置的文件用find,找“系统里某个东西在哪”用locate,找文件内容用grep -r。grep -rn "关键字" ./src这个组合我每天要用几十次,-r递归、-n显示行号、-i忽略大小写、--include="*.js"限定文件类型。
3. 权限与用户:把这套组合拳打明白
3.1 权限位的二进制本质与umask计算
Ubuntu的权限模型是三个身份、三组权限。身份是属主(u)、属组(g)、其他(o),权限是读(r=4)、写(w=2)、执行(x=1)。把三个数字加起来就是一位八进制数,比如rwx是 4+2+1=7,rw-是 6,r-x是 5,r--是 4。所以chmod 755 file展开就是属主 rwx、属组 r-x、其他 r-x。
chmod 644 config.yaml # rw-r--r--,普通配置文件的标准权限 chmod 755 run.sh # rwxr-xr-x,可执行脚本 chmod 600 ~/.ssh/id_rsa # 私钥必须是600,否则ssh会拒绝使用 chmod 700 ~/.ssh # ssh目录 chmod -R 755 /data/www # 递归改目录 chmod u+x script.sh # 符号法:给属主加执行权限 chmod go-w file # 去掉属组和其他的写权限符号法在微调时比数字法方便,+加、-减、=设。chmod a+r是给所有人加读权限,a代表 all。递归改权限时要注意目录和文件应该分开处理,目录需要执行位才能进入,文件通常不需要,所以上面 2.3 里那两个find -exec是有意分开写的。
umask决定了新建文件的默认权限。计算方式是“最大权限减去umask”:目录最大是777,文件最大是666(出于安全考虑不默认给执行位)。默认umask是022,那么新建目录是 777-022=755,新建文件是 666-022=644。如果你在共享目录里工作,希望同组成员能互相改文件,可以把umask设成002,得到目录775、文件664。
umask # 查看当前值 umask 002 # 临时修改,只对当前shell有效3.2 sudo的正确姿势与几条保命习惯
sudo的设计目标是“以最小必要权限执行单条命令”,但很多人把它用成了“所有命令前面加个sudo就完事”。这样做的问题在于,一旦你养成习惯,某天在错误的目录下执行sudo rm -rf *,后果是不可逆的。
几个我认为必须养成的习惯:第一,能用普通用户做的事绝不用sudo,sudo只在真正需要写系统目录、改服务配置、装软件时使用;第二,sudo !!可以给上一条命令补上sudo,这个比按上箭头再用方向键挪到行首要快;第三,sudo -i进入root交互shell,但我不推荐长期停在root shell里,容易忘记自己是谁;第四,修改sudoers文件必须用visudo,因为它会做语法检查,直接编辑/etc/sudoers写错一个字符就可能把自己锁在外面。
sudo !! # 给上一条命令加sudo重跑 sudo -u www-data whoami # 以指定用户身份执行 sudo -l # 查看当前用户能执行哪些sudo命令 sudo visudo # 安全编辑sudoerssudo的密码缓存默认是15分钟,期间再执行不用重复输。想立刻清掉缓存用sudo -k。另外!!和!$这两个历史扩展符号值得记:!!是上一条完整命令,!$是上一条命令的最后一个参数。比如你先ls /etc/nginx/sites-available/,接着想编辑其中一个文件,直接sudo vim !$就行。
注意:
sudo后面接重定向时,>是由当前shell执行的,不是sudo执行的。所以sudo echo "x" > /etc/xxx会报权限拒绝。正确写法是echo "x" | sudo tee /etc/xxx或者sudo sh -c 'echo "x" > /etc/xxx'。这个坑几乎人人都踩过。
3.3 SUID、SGID与粘滞位:三个特殊权限位
除了常规的rwx,还有三个特殊权限位,日常用得少但遇到时要认得。SUID(4)作用于可执行文件,让执行者临时获得文件属主的权限,最典型的就是/usr/bin/passwd,普通用户能改自己的密码就是因为这个。SGID(2)作用于目录时,让目录里新建的文件继承目录的属组,团队共享目录会用到。粘滞位(1)作用于目录,让用户只能删除自己的文件,/tmp的权限是1777,那个开头的1就是粘滞位,这就是为什么你能删除自己在/tmp里的文件,却删不掉别人的。
# 设置粘滞位 chmod 1777 /data/share # 或 chmod +t /data/share # 设置SGID让新文件继承属组 chmod 2775 /data/team # 或 chmod g+s /data/team # 查找系统中的SUID文件(安全自查用) find / -perm -4000 -type f 2>/dev/null最后这条自查命令我在接手任何一台陌生机器时都会跑一遍,看看有没有不该出现的SUID程序。正常系统里SUID文件数量是有限的,多出来的就要留意。权限这部分最后强调一句:chown改属主属组需要root权限,chgrp改属组,chown user:group file这个写法最省事,冒号前后分别是用户和组。
4. 软件包管理:apt、dpkg、snap各管一摊
4.1 apt日常操作:update和upgrade到底差在哪
很多人对apt update和apt upgrade的区别含糊,简单说:update是刷新本地软件源索引,不装任何东西;upgrade是拿新索引去比对,把可升级的包升上去。只做upgrade不做update,你升级的还是旧索引里的版本。
sudo apt update # 刷新索引,装软件前必做 sudo apt upgrade # 升级已装软件,不删包 sudo apt full-upgrade # 升级并允许处理依赖冲突(可能删包) sudo apt install nginx # 安装 sudo apt install -y nginx # 自动确认 sudo apt remove nginx # 卸载但保留配置 sudo apt purge nginx # 卸载并删配置 sudo apt autoremove # 清理不再需要的依赖 sudo apt search 关键词 # 搜索 apt show nginx # 看包详情 apt list --installed # 列出已装包 apt-cache policy nginx # 看可用版本和来源remove和purge的区别很重要。配置文件通常放在/etc下,remove之后重新安装,旧配置还在,这既是好处也是坑——你改了配置导致服务起不来,卸载重装发现还是起不来,因为配置没被清掉。所以“重装大法”要用purge。
apt-mark hold 包名可以锁定某个包不参与升级,我在维护老旧环境时常用,防止某次upgrade把关键依赖带上去。解锁是apt-mark unhold。
4.2 dpkg:处理本地deb包和查文件归属
dpkg是apt底层的包管理工具,直接操作deb文件。最常用的两个场景:装本地下载的deb包,以及查某个文件属于哪个包。
sudo dpkg -i package.deb # 安装本地deb sudo apt -f install # 修复依赖缺失(dpkg -i报依赖错后用这个) dpkg -l | grep nginx # 列出已装的nginx相关包 dpkg -L nginx # 列出nginx包安装了哪些文件 dpkg -S /usr/sbin/nginx # 反查文件属于哪个包 dpkg -P package # 彻底卸载dpkg -i的经典问题是依赖没装,报一堆错误然后包处于半配置状态。别慌,跑一次sudo apt -f install让apt把缺的依赖补上就行。dpkg -S这个反查功能在排查“这个命令是哪来的”“这个配置文件被哪个包覆盖了”时特别有用,比which更进一层,因为它能告诉你文件归属而不管它在不在PATH里。
4.3 snap、PPA与其他来源
snap是另一套打包体系,优点是把依赖一并打包,版本更新,缺点是体积大、启动稍慢。snap list看已装、sudo snap install 包名安装、sudo snap remove 包名卸载、snap refresh全部更新。有些软件官方只提供snap版本,比如某些IDE和设计工具,这时候没得选。
PPA是个人维护的软件源,加进来就能用apt装更新的版本:sudo add-apt-repository ppa:xxx/yyy,然后sudo apt update。PPA的好处是版本新,风险是稳定性和维护者可靠性参差,生产环境要慎重。删PPA用sudo add-apt-repository --remove ppa:xxx/yyy。
提示:装完软件后
apt install报“有几个软件包无法下载”,八成是源地址不通或者源里的版本已下架。先sudo apt update刷新,还不行就检查/etc/apt/sources.list和sources.list.d里的源是否还能访问。这类问题排查思路比记住具体命令更重要。
5. 系统诊断:进程、磁盘、日志三板斧
5.1 进程排查四板斧:ps、top、kill、systemctl
进程出问题时,我的排查顺序固定是:先看“谁在跑”,再看“谁在吃CPU/内存”,然后“要不要杀”,最后“怎么让它常驻”。
ps aux | grep nginx # 找进程 ps -ef --forest # 看进程树 pgrep -af python # 按名字找PID,-a显示命令行 top # 实时监控 htop # 更好用的版本(需安装)top里几个快捷键得知道:P按CPU排序、M按内存排序、k杀进程、1展开多核、q退出。htop更直观,F6 可以选排序字段,F9 杀进程,鼠标也能点。
杀进程要分清信号:kill -15 PID(SIGTERM,请求优雅退出,默认)和kill -9 PID(SIGKILL,强制杀死)。顺序上永远是先15后9,因为 -9 不给进程清理资源的机会,数据库这类服务被 -9 可能损坏文件。pkill 进程名按名字杀,killall 进程名杀所有同名进程。
如果要让进程在退出终端后继续跑,nohup command &是最基础的写法,输出重定向到nohup.out。更规范的做法是写成systemd服务,sudo systemctl start/stop/restart/status 服务名,systemctl enable 服务名开机自启,journalctl -u 服务名 -f实时看日志。这套东西学会了,服务管理基本不用愁。
Ctrl+Z # 把当前前台进程挂起 jobs # 查看挂起的任务 bg %1 # 让任务1到后台继续跑 fg %1 # 把任务1调回前台Ctrl+Z这个用法很多人不知道,跑一个耗时命令想中断又不想杀,按Ctrl+Z挂起,做完别的事fg调回来,比重新跑一遍省事。
5.2 磁盘与内存:df和du的配合逻辑
磁盘满了是所有运维事故里最常见的一类。诊断顺序是:df -h看哪个挂载点满了,du逐层定位是哪个目录大。
df -h # 各挂载点使用情况 df -i # inode使用情况(小文件太多时会满) du -sh /var/* # /var下各目录大小 du -h --max-depth=1 /var | sort -h # 按大小排序 find / -type f -size +1G 2>/dev/null # 找出大于1G的文件df和du结果对不上是个经典现象。原因通常是“文件被删除但进程还持有句柄”,磁盘空间没释放。用sudo lsof | grep deleted能找到这些进程,重启对应服务即可释放。还有一种情况是挂载点被覆盖,目录里原有文件被新挂载遮蔽,du看不到但空间确实占着,mount看一下挂载顺序能发现。
inode满这个坑更隐蔽:df -h显示空间充足,但就是写不进去。原因是一个目录下有几十万个小文件,inode用完了。df -i一看 IUse% 100% 就明白了。解决办法是清理小文件,或者建文件系统时调大inode数量。
内存方面free -h输出里的available才是真正可用的量,free那一列数字小是正常的,因为Linux会尽量用空闲内存做缓存。真正要关注的是available掉到很低,同时swap使用量在涨,那说明内存确实紧张了。
5.3 日志与网络:journalctl和ss的实战用法
journalctl是systemd体系的日志入口,功能比翻/var/log/messages强太多。
journalctl -u nginx --since "1 hour ago" # 某服务最近1小时日志 journalctl -f # 实时跟踪 journalctl -p err -b # 本次启动的错误级别日志 journalctl --disk-usage # 日志占了多少空间 sudo journalctl --vacuum-size=500M # 清理到只剩500M--since和--until支持很灵活的时间写法,"2024-01-01 10:00"、"yesterday"、"30 min ago"都行。-p按级别过滤,err及以上会列出真正的问题,比翻全量日志高效。
网络排查的固定套路是:ip a看网卡和IP,ip route看路由,ss -tulnp看监听端口(-tTCP、-uUDP、-l监听、-n数字端口、-p显示进程),ping测连通,curl -v测HTTP,dig或nslookup查解析。ss基本已经取代了老的netstat,参数含义一样,但速度快得多。
ss -tulnp | grep 8080 # 看8080端口被谁占了 ip a | grep inet # 看本机IP curl -I https://example.com # 只看响应头6. 常见问题与排查技巧实录
6.1 高频问题速查表
下面这张表是我这些年被问最多的问题汇总,按“现象—原因—解决”三列整理,遇到时直接对号入座。
| 现象 | 常见原因 | 解决方式 |
|---|---|---|
apt报 “Could not get lock” | 另一个apt进程在跑,或上次异常退出留下锁文件 | ps aux | grep apt找到进程,等它结束或sudo kill;删锁文件sudo rm /var/lib/dpkg/lock*后sudo dpkg --configure -a |
终端里Ctrl+S后无响应 | 流控暂停 | 按Ctrl+Q恢复 |
命令提示Permission denied | 权限不足或文件系统只读 | 检查ls -l权限和挂载状态mount | grep ro |
command not found但明明装了 | PATH没包含,或装在了非标准路径 | echo $PATH检查,which/whereis定位,必要时写全路径或加软链 |
磁盘满了但du找不到大文件 | 删除的文件被进程占用 | sudo lsof | grep deleted,重启对应进程 |
| 磁盘有空间但写不进去 | inode耗尽 | df -i确认,清理小文件目录 |
| 修改配置后服务起不来 | 配置语法错 | 先用服务自带的-t测试,如nginx -t,再重启 |
| 快捷键失效 | 输入法或优化工具抢占 | 设置里查冲突,gsettings恢复默认 |
| 中文显示成方块 | 缺中文字体 | sudo apt install fonts-noto-cjk,重建缓存fc-cache -fv |
6.2 几个不那么常见但很值钱的坑
第一个是软链接被cp -r展开的问题。cp -r默认会跟随软链接,把链接指向的内容复制成实体文件,结果目录体积暴涨。正确做法是用cp -a,它保留链接本身。做迁移和备份时这个差别可能是几十G。
第二个是rm通配符没匹配到任何文件时的行为。bash默认下rm *.log如果没有任何匹配,会把*.log这个字面量传给rm,报“No such file”。但如果你开了shopt -s nullglob,它就什么都不做。更危险的是rm -rf /path/*里如果路径写错,可能匹配到意料之外的东西。我的习惯是删除前先ls一遍同样的通配符看清楚。
第三个是sudo执行带管道命令时的权限问题。sudo cat file | grep xxx里cat有权限但grep没有,结果正确;而sudo echo x > file里重定向是当前用户执行的,会失败。前面提过用tee解决,这里再补一个sudo -s进入有root权限的shell处理复杂管道。
第四个是脚本里的相对路径问题。cron定时任务执行时工作目录不是你的home,脚本里所有相对路径都会失效。解决办法是脚本开头cd "$(dirname "$0")"切到脚本所在目录,或者全程用绝对路径。这个问题我在不同环境里遇到过四五次,每次都是排查半天。
第五个是tar解压覆盖的隐蔽风险。tar -xzf默认直接覆盖同名文件,不提示。而且如果压缩包里带了绝对路径或../,老版本tar会直接解压到目标目录之外。现在较新的tar会拒绝绝对路径,但养成tar -tzf先看内容的习惯没坏处。
提示:给任何脚本加上
set -euo pipefail三件套是提高可靠性的低成本手段。-e遇错退出,-u未定义变量报错,-o pipefail让管道中任一环失败都能被捕获。加上之后你会发现以前“静默失败”的问题全都暴露出来了。
7. 把效率固化下来:别名、函数与历史技巧
7.1 alias和shell函数:把长命令压成一两个字母
快捷键解决的是窗口和终端层面的切换,真正在终端里敲命令时的效率,靠的是别名和函数。别名写在~/.bashrc里,改完source ~/.bashrc生效。
# ~/.bashrc 里我常驻的几组 alias ll='ls -alFh' alias la='ls -A' alias ..='cd ..' alias ...='cd ../..' alias grep='grep --color=auto' alias gs='git status' alias gd='git diff' alias ports='ss -tulnp' alias myip='curl -s ifconfig.me'别名适合固定参数的命令,如果参数需要动态变化,用函数更合适。
# 创建目录并立刻进入 mkcd() { mkdir -p "$1" && cd "$1"; } # 快速备份某个文件 bak() { cp -a "$1" "$1.bak.$(date +%Y%m%d%H%M)"; } # 查看某端口占用进程 port() { ss -tulnp | grep ":$1 "; }mkcd这个函数我用得最多,建目录、进目录一次完成。bak在改配置前敲一下,出问题原文件还在。这类小工具不需要多,五六个贴合自己习惯的就够用,关键是真的去用。
7.2 历史命令和反向搜索:Ctrl+R的进阶玩法
Ctrl+R是终端里最被低估的快捷键。按下之后输入关键字,它会从历史里反向匹配,每按一次Ctrl+R继续往前找,找到后按Enter直接执行,按→或Tab是取出来编辑不执行。
历史命令还有几个扩展符号:!!上一条命令,!$上一条的最后一个参数,!^上一条的第一个参数,!123执行历史里第123条,!git执行最近一条以git开头的命令。history | grep xxx也能搜,但比Ctrl+R多敲好几个字符。
history 20 # 看最近20条 history | grep ssh # 搜历史里的ssh命令 fc -l -10 # 同上,另一种写法历史记录里有些命令包含密码这类敏感信息,可以在命令前加一个空格让它不记录,前提是设置了HISTCONTROL=ignorespace。这个细节在共享环境里值得注意。
7.3 一个小习惯带来的长期收益
最后分享一个我坚持了很多年的小习惯:把每次解决掉的问题顺手记成一条命令或一句注释,攒在自己的cheatsheet文件里。Ubuntu这套指令体系庞大,没人能全记住,但每个人的高频场景其实是有限的,通常两三百条命令就覆盖了95%的日常工作。有了自己的速查表,遇到问题先翻自己的记录,比搜索引擎快,而且记录下来的是经过自己验证的、带上下文的答案。
配合这个习惯,我把提示符也改了,让它显示完整路径和上一条命令的退出码,出错时一眼能看到。改法是在~/.bashrc末尾加一行export PS1='\[\e[32m\]\u@\h\[\e[0m\]:\[\e[34m\]\w\[\e[0m\]\$ ',虽然长得有点吓人,但改完之后定位问题确实方便。这些零散的配置和快捷键叠加起来,就是那个“同样的任务别人花十分钟你花两分钟”的差距来源。工具本身不复杂,难的是持续把手上的动作优化掉一点点,日积月累就是效率上的分水岭。