多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

GRUB rescue急救:从Minimal BASH-like到引导重建

GRUB rescue急救:从Minimal BASH-like到引导重建 很多人第一次见到这行字是在一个本该出现系统登录界面的清晨屏幕全黑只有几行白字最上面那句就是Minimal BASH-like line editing is supported下面跟着一句冷冰冰的grub rescue。那一瞬间大多数人的第一反应是我的 Linux 是不是废了第二反应是BASH 坏了怎么办。先给个定心丸系统盘里的数据九成九还在坏掉的是引导程序 GRUB 的启动地图而不是你的操作系统本身。这台机器现在处于 GRUB 的降级急救模式它把一套模仿 BASH 行编辑习惯的极简命令行丢给你让你自己想办法把系统拉起来。这篇文章面向所有装过双系统、动过分区、做过磁盘克隆、被 Windows 更新折腾过的人也面向想搞清楚 GRUB 引导链条到底怎么运转的人。我会先把这条提示背后的机制讲透再给你两套能直接抄的修复流程一套是现场手敲命令临时进系统一套是用启动盘彻底重建引导最后顺带把几个和 BASH 相关的高频报错一起排掉。1. 先搞懂这条提示到底在说什么1.1 GRUB 的两个急救室grub 与 grub rescue要理解这行提示得先知道正常开机时 GRUB 做了什么。以传统 BIOS 主板为例固件读完硬盘第一个扇区的引导代码后把控制权交给 GRUB 的第一阶段代码第一阶段代码的目标只有一个——找到并加载第二阶段的核心镜像core.img这个镜像通常被塞在分区表后面那段几十 KB 的空隙里。core.img里编译进去了一条关键信息prefix也就是我的配置文件和各种模块放在哪个目录下典型值形如(hd0,msdos1)/boot/grub。拿到 prefix 之后GRUB 会去那个目录加载normal.mod读取grub.cfg然后给你画出那个熟悉的系统选择菜单。整条链条里任何一环断了GRUB 都会退回最后一层保底机制——加载内置的 rescue 模块。这个模块小得可怜只认识ls、set、insmod、unset、lsmod、prefix这几个命令功能就是让我看看磁盘上有什么、把路径设对、再把完整模块拉进来。它内置了一个极简的命令行解释器支持 TAB 补全、方向键翻历史、光标移动这些行编辑动作用起来很像 BASH所以它才在提示里自称 BASH-like line editing。这句话不是报错内容而是 GRUB 在自我介绍告诉你我现在只有个简版命令行TAB 可以补全命令。这是全网误读最多的一句话很多人看到 BASH 就跑去修 bash 环境方向从一开始就偏了。区分两个急救室很重要它们的提示符完全不一样能做的事情也差得很远。提示符触发条件可用命令典型表现grubnormal.mod已加载但grub.cfg缺失或内容为空几乎全部命令含linux、initrd、boot直接进命令行没有菜单grub rescue找不到 prefixnormal.mod都没能加载只有ls、set、insmod等少数几个伴随Minimal BASH-like line editing is supportedLinux 的bash系统已启动进入用户态全部 Shell 功能提示符是$或#这两个提示符的修复路径前半段一样后半段分叉grub下你可以直接linux加initrd启动内核而grub rescue下敲linux会直接回你一句 Unknown command必须先insmod normal把完整模块请进来。这个细节决定了后面第 2 章的两种打法。1.2 为什么偏偏是只剩一个命令行搞清楚了 GRUB 的工作方式触发原因就很好归纳了——本质上是**GRUB 找不到自己的配置目录或者配置目录里的东西打不开**。前者是路径问题后者是文件系统或文件损坏问题。常见的触发场景我按出现频率排个序。第一类是分区表被改写。装 Windows 的时候安装程序会理所当然地重写引导记录Windows 的大版本更新偶尔也会顺手把引导顺序改掉把自家的引导项顶到第一位。第二类是/boot或/boot/grub被删、被清空、被格式化比如清理磁盘空间时手滑或者跟着某些教程rm -rf敲快了。第三类是core.img里记录的 prefix 失效具体来说就是分区编号变了——加了一块新硬盘、改了 BIOS 里的硬盘顺序、从 U 盘启动过一次、把 NVMe 系统盘从 M.2 槽位挪到另一个槽位都可能让原来的(hd0,msdos1)变成(hd1,msdos1)GRUB 按老地址去找自然扑空。第四类是整盘克隆或者虚拟机迁移。用克隆工具把系统盘复制到新盘后分区的 UUID 全变了grub.cfg和/etc/fstab里还写着旧 UUIDGRUB 去找不存在的分区直接掉进 rescue。第五类是文件系统本身出了问题比如断电导致的 ext4 日志未回放GRUB 自带的ext2.mod读不出来ls (hd0,1)/会告诉你unknown filesystem。第六类是 UEFI 和 Legacy 两种启动方式混着用比如原本是 Legacy 装的系统你却在 UEFI 模式下启动固件读到的引导信息对不上。触发原因现场特征修复难度分区表被 Windows 改写上次正常装完系统开不了机低重建引导即可/boot/grub被删ls (hd0,x)/boot里没有 grub 目录中需要重装 GRUB磁盘编号/顺序变化提示符出现前没有任何异常低改回顺序或重装克隆盘 UUID 变化手动引导能进系统重启又挂中需要改 fstab 与 cfg文件系统损坏ls报unknown filesystem高先修复文件系统UEFI/Legacy 混用主板启动项里能看到两个同名设备中需要切回正确模式2. 进系统前的急救手敲命令把系统拉起来2.1 用 ls 摸清楚磁盘和分区的编号进入grub rescue之后先深呼吸第一条命令永远是ls不带任何参数grub rescue ls (hd0) (hd0,msdos1) (hd0,msdos5) (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)看到的东西是盘和分区两个层级。(hd0)代表第一块盘本身(hd0,msdos1)代表它上面的第一个 MBR 分区(hd0,msdos5)是第一个逻辑分区MBR 扩展分区里的逻辑分区从 5 开始编号这是很多人会愣一下的地方。GPT 分区表则显示成(hd1,gpt1)这种形式编号是连续的。接下来逐个分区探测内容看哪个里面有系统grub rescue ls (hd0,msdos1)/ grub rescue ls (hd0,msdos5)/判断依据很简单/boot/grub或者/grub目录出现在哪个分区里那个分区就是你要的。如果/boot是独立分区你会看到该分区根目录下直接有一个grub文件夹如果/boot和根分区合在一起你会看到boot文件夹往里再钻一层才是grub。这个区别直接决定了后面 prefix 怎么写也是新手翻车最集中的地方。注意如果ls (hd0,1)/返回的是unknown filesystem而不是文件列表说明 GRUB 读不出这个分区的文件系统。此时不要急着设 prefix先把这块盘接到另一台机器上做一次fsck或者用启动盘里的fsck.ext4 -y /dev/sda1修复修完再回来。2.2 set root 与 set prefix 的正确写法确认了分区之后设置两个变量grub rescue set root(hd0,msdos5) grub rescue set prefix(hd0,msdos5)/boot/grubroot是我要在哪个分区上找东西prefix是GRUB 的模块和配置文件具体在什么路径。prefix 指向的是包含grub文件夹的那个目录而不是grub文件夹本身这一点务必咬死。举个例子如果你的分区布局是/dev/sda1挂载到/boot那么 prefix 应该是(hd0,msdos1)/grub如果/boot没有独立分区直接是根分区(hd0,msdos5)下的目录那 prefix 才是(hd0,msdos5)/boot/grub。写错一个层级下一步insmod normal就会回你file not found而这个报错信息几乎不会告诉你错在哪一级只能自己回头核对。设置完可以用set单独打出来看一眼当前状态用ls配合验证一下路径是否存在grub rescue set root(hd0,msdos5) prefix(hd0,msdos5)/boot/grub grub rescue ls (hd0,msdos5)/boot/grub能列出normal.mod、grub.cfg、i386-pc这些东西说明路径对了。2.3 insmod normal 与 normal 的两条路径路径确认无误后加载完整模块并切换到正常模式grub rescue insmod normal grub rescue normal成功的话屏幕会刷出系统选择菜单你直接选第一项回车系统就起来了。如果菜单没出现但提示符变成了grub说明模块加载成功但grub.cfg有问题——可能是文件被清空也可能是里面引用的分区 UUID 全部失效。在grub提示符下你可以手动把内核拉起来这套命令在 rescue 模式下加载完 normal 之后同样适用grub set root(hd0,msdos5) grub linux /boot/vmlinuz-5.15.0-91-generic root/dev/sda5 ro grub initrd /boot/initrd.img-5.15.0-91-generic grub boot这里有两个关键细节全是血泪教训换来的。第一内核文件名不要靠记忆去敲用 TAB 补全。输入/boot/vmlinuz之后按 TABGRUB 会把候选列出来如果只有一个就自动补全有多个就列成一行一行给你挑。第二linux后面那个root参数用的是内核认得的设备名比如/dev/sda5、/dev/nvme0n1p2不是 GRUB 的(hd0,msdos5)。这两个命名体系是独立的混着写会得到VFS: Cannot open root device的经典报错。GRUB 的编号从 0 开始数磁盘、从 1 开始数分区Linux 内核那边/dev/sda从 a 开始排、分区从 1 开始排NVMe 设备还多一个p。见到(hd0,gpt2)就对应/dev/sda2或/dev/nvme0n1p2具体是哪块要看ls的结果顺序。grub linux /boot/vmlinuzTAB grub initrd /boot/initrd.imgTAB提示如果insmod normal报unknown filesystem说明该分区的文件系统模块缺失。可以试着先加载对应模块例如insmod ext2ext2/3/4 共用这一个模块再执行insmod normal。这个顺序问题文档里基本不写但现场很有用。2.4 别急着欢呼这只是临时的手敲命令能进系统说明硬盘数据完好问题纯粹出在引导层。但要清醒地认识到你在 rescue 模式里做的所有设置只存在内存里一重启全没了。很多人看到系统起来了重启一下又回到黑屏然后误以为修不好其实是没做持久化。进入系统后第一件事是确认根分区的挂载情况和 GRUB 配置的位置lsblk -f cat /etc/fstab ls -l /boot/grub/grub.cfg mount | grep bootlsblk -f会告诉你每块盘、每个分区的文件系统类型、UUID 和挂载点这个输出后面重建引导时还要用。cat /etc/fstab让你知道系统认为自己的根分区是哪个如果这里的 UUID 和lsblk报出来的对不上那问题就找到了——克隆盘导致的 UUID 错乱需要把 fstab 里的 UUID 改成新的。确认没问题之后在能正常进系统的前提下可以直接就地重装 GRUB不必用启动盘sudo grub-install /dev/sda # Legacy BIOS 场景参数是整块盘不是分区 sudo update-grub # Debian/Ubuntu 系RHEL 系用 grub2-mkconfig -o /boot/grub2/grub.cfgUEFI 场景则要指明目标平台和 EFI 分区sudo grub-install --targetx86_64-efi --efi-directory/boot/efi --bootloader-idubuntu --recheck sudo update-grubupdate-grub会扫描系统里所有的内核镜像和已存在的操作系统重新生成grub.cfg。跑完之后重启验证一次如果还回 rescue说明问题不在配置生成而在更底层的引导记录那就得走第 3 章的启动盘流程。3. 一次性修好用启动盘重建 GRUB 引导3.1 准备工作与分区识别当系统已经完全进不去或者手敲命令加载 normal 也失败时最稳的办法是从启动盘进去修。准备一个 8GB 以上的 U 盘用镜像写入工具把某个 Linux 发行版的安装镜像写进去实体机推荐用 Rufus 或 balenaEtcher命令行党用dd也可以。写入之前记得备份 U 盘里的东西这个过程会清空整块盘。插上 U 盘开机时按主板对应按键进启动菜单常见的是 F12、F11、Esc、F8各家不同选择 U 盘启动。进入安装界面后不要真的安装选试用模式进入一个完整的桌面环境然后打开终端开始干活。第一步永远是识别分区结构别凭感觉lsblk -f sudo fdisk -l sudo blkidlsblk -f输出的FSTYPE和MOUNTPOINT列最有价值标着fat32或vfat、大小几百 MB 的通常是 UEFI 的 EFI 系统分区标着ext4且几百 MB 到 1GB 的很可能是独立的/boot容量最大、标着ext4或btrfs的一般是根分区。如果你用的是 LVM 或者加密根分区lsblk里会看到lvm类型还需要先激活卷组这一步后面单独说。3.2 BIOS 与 UEFI 两套修复流程的差异这两种引导方式的修复命令完全不同先看对比表再看具体操作。对比项Legacy BIOS MBRUEFI GPT引导代码位置整块磁盘的第一个扇区MBREFI 系统分区里的.efi文件需要挂载的分区根分区有独立/boot也要挂根分区 EFI 分区安装命令目标grub-install /dev/sdagrub-install --targetx86_64-efi --efi-directory...引导项管理由主板固件自动识别efibootmgr管理启动顺序常见坑参数写成分区号导致失败EFI 分区没挂载或不是 FAT32分区表容量限制主分区最多 4 个支持 128 个分区判断自己属于哪种可以在启动盘的终端里跑一句[ -d /sys/firmware/efi ] echo 当前是 UEFI 模式 || echo 当前是 Legacy 模式注意这句判断的是你现在以什么模式启动如果 U 盘是以 Legacy 方式启动的而系统原本是 UEFI 安装的这句会误报。更可靠的办法是看硬盘分区表类型sudo fdisk -l里显示Disklabel type: gpt且存在 EFI 分区基本就是 UEFI 系统。3.3 chroot 修复的完整步骤拆解修复的核心思路是把硬盘上的系统临时接管到启动盘环境里让grub-install以为自己运行在正常系统中。这就是 chroot。每一步都有讲究我按顺序写清楚。# 1. 挂载根分区按你自己的设备名替换 sudo mount /dev/nvme0n1p2 /mnt # 2. 如果 /boot 是独立分区先挂它 sudo mount /dev/nvme0n1p3 /mnt/boot # 3. 如果是 UEFI挂载 EFI 分区 sudo mount /dev/nvme0n1p1 /mnt/boot/efi挂载顺序不能乱必须先挂根分区再挂子目录否则子分区会被根分区覆盖掉变成空目录这个坑我踩过一次现象是 chroot 进去之后/boot里什么都没有还以为是分区坏了。# 4. 把系统运行所需的关键目录绑定进去 sudo mount --bind /dev /mnt/dev sudo mount --bind /dev/pts /mnt/dev/pts sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys # 5. 如果修复过程需要联网安装包把 DNS 配置带进去 sudo cp /etc/resolv.conf /mnt/etc/resolv.conf # 6. 切换根目录 sudo chroot /mnt /bin/bash--bind这几步看起来多余实际很关键。/dev不给grub-install找不到磁盘设备/proc和/sys不给一些工具探测硬件信息时会报奇怪的错误。省略它们有时候也能跑通但一旦出错报错信息往往误导性极强排查成本远高于多敲四行命令。进入 chroot 之后先验证身份ls / cat /etc/os-release能看到完整的根目录结构和发行版信息说明接管成功。接下来重建引导# UEFI 系统 grub-install --targetx86_64-efi --efi-directory/boot/efi --bootloader-idubuntu --recheck # Legacy 系统 grub-install --targeti386-pc --recheck /dev/nvme0n1 # 重新生成配置文件 update-grub # 或者通用写法 grub-mkconfig -o /boot/grub/grub.cfg几个参数的含义值得说透。--recheck让 grub-install 重新探测设备映射避免使用可能过期的缓存--bootloader-id是写进 EFI 分区和固件启动项里的名字随便叫什么都行但如果你希望和原来的保持一致比如原来的叫 ubuntu就照原样写--efi-directory必须指向已挂载的EFI 分区挂载点没挂载就会报failed to get canonical path of /boot/efi这个报错的字面意思和真实原因之间隔了十万八千里很多人在网上翻半天找不到答案。收尾工作同样不能省exit # 退出 chroot sudo umount -R /mnt # 递归卸载一次搞定所有挂载点 sudo reboot注意umount -R的顺序是从内到外自动处理的比手动一条条卸载靠谱得多。如果卸载时报target is busy先cd /离开当前目录再用sudo fuser -m /mnt看看是谁占着。3.4 验证引导项与启动顺序UEFI 系统重启前最好在启动盘环境里确认一下引导项写对了sudo efibootmgr -v输出会列出所有固件启动项形如Boot0001* ubuntu HD(1,GPT,...)/\EFI\ubuntu\grubx64.efi。如果这里的路径是错的或者你的系统项被排到了后面可以调整顺序sudo efibootmgr -o 0001,0000,0002这条命令把启动顺序重排成 0001 优先。如果efibootmgr里根本找不到你的系统项说明grub-install的 NVRAM 写入没成功可能是主板固件的问题可以再进一次 chroot 重跑一遍或者用--no-nvram参数跳过写入、手动在固件设置界面里添加引导文件路径。重启后如果进了系统还有几件事值得做检查/etc/fstab里的 UUID 和lsblk -f是否一致跑一次sudo grub-install对应命令确认无误把这次用到的命令记到自己的笔记里。下次真出事的时候翻笔记比翻搜索引擎快得多。4. 修完还会复发几个容易被忽略的坑4.1 Windows 更新和系统重装导致的引导被顶掉Windows 在引导顺序上相当霸道安装过程和某些大版本更新都会把自家的引导项顶到第一位甚至直接覆盖 MBR 里的引导代码。如果你用的是双系统正确的做法是先装 Windows 再装 Linux这样后装的 GRUB 才能接管引导并自动识别 Windows 分区。顺序反了的话每次 Windows 更新都可能让你重新体验一遍黑屏。如果已经被顶掉了不用慌进 Linux 后跑一次sudo update-grub它会自动扫描到 Windows 的引导文件并加进菜单。如果连 Linux 都进不去了就按第 3 章的流程用启动盘修修完记得在固件设置里把 Linux 的引导项提到前面很多主板的启动菜单里可以直接拖拽排序。4.2 磁盘克隆后 UUID 变了手动引导能进但重启就挂这个现象很有迷惑性手敲命令能进系统说明引导文件和内核都在但一重启就回 rescue说明系统自己生成的配置指向了错误位置。根源在 UUID。克隆之后新分区的 UUID 和旧盘完全不同而/etc/fstab和/boot/grub/grub.cfg里还写着旧的那串字符。修复思路有两条。第一条是迁就系统把 fstab 和 grub.cfg 里的 UUID 改成新值sudo blkid # 查出新的 UUID sudo nano /etc/fstab # 逐个替换 sudo update-grub # 用新信息重新生成 cfg第二条是迁就配置把新分区的 UUID 改回旧的这样连 fstab 都不用动sudo tune2fs -U 原来的UUID /dev/sda2第二条更省事但前提是你还留着旧 UUID 的记录而且新旧分区不能同时在线上UUID 重复会导致挂载混乱。个人建议还是走第一条把配置改对一次做干净。4.3 多硬盘环境下 GRUB 的盘符不是固定的(hd0)的具体含义会变。它取决于固件把哪块盘排在了最前面而这件事在 BIOS 里可以手动调也可能因为插了一块新的移动硬盘而改变。同样的道理SATA 接口换了位置、NVMe 硬盘插到另一个 M.2 槽都可能让系统盘从hd0变成hd1。这里有个实用的对照表现场排查时能省不少时间Linux 设备名GRUB 写法说明/dev/sda(hd0)第一块 SATA/SCSI 盘/dev/sda1(hd0,msdos1)MBR 第一个主分区/dev/sda5(hd0,msdos5)MBR 第一个逻辑分区/dev/sda2(hd0,gpt2)GPT 第二分区/dev/nvme0n1p2(hd0,gpt2)前提是这块 NVMe 排第一/dev/sdb1(hd1,msdos1)第二块盘要彻底避免这类问题可以在系统装上之后就把引导项写入 NVRAMUEFI 场景或者确保grub-install时指定的是正确的整块磁盘。更稳妥的做法是养成习惯每次动过硬盘硬件配置之后先开机验证一次出问题的是当场就能定位比过几个月突然黑屏再排查容易得多。4.4 LVM 与加密根分区的额外步骤如果根分区在 LVM 上chroot 之前需要先激活卷组sudo vgscan sudo vgchange -ay ls /dev/mapper/看到类似vg-root、vg-swap的设备后挂载/dev/mapper/vg-root而不是物理分区。如果根分区是加密的还需要先解密sudo cryptsetup luksOpen /dev/nvme0n1p3 cryptroot然后挂载/dev/mapper/cryptroot。这层解密的顺序不能颠倒否则你会看到一堆设备不存在的报错。加密系统修引导的完整流程比普通系统长一倍操作前务必确认自己知道所有密码中途卡在密码提示上是很尴尬的事。5. 顺手排掉几个和 BASH 有关的高频报错5.1 -bash: crontab: command not found 到底缺了什么这个报错的字面意思很直白找不到crontab这个命令。但它背后的原因有三种得分开处理。第一种是真没装。最小化安装的系统往往不带计划任务组件。Debian/Ubuntu 系装sudo apt install cronRHEL/CentOS/Fedora 系装sudo dnf install cronie或sudo yum install cronie。装完之后记得确认服务在跑systemctl status crond没启动就systemctl enable --now crond。第二种是装了但PATH里没有。用非交互式 shell 执行脚本时环境变量可能被精简PATH里只有/usr/bin:/bin而crontab在/usr/bin/crontab的话本该能找到但如果装在/sbin或其他位置就会失联。排查办法是先command -v crontab比which更可靠因为它认 shell 函数和别名再用type -a crontab看所有候选。如果command -v有输出但直接敲没有那就是别名或者PATH顺序的问题。第三种是权限问题。普通用户执行crontab -l看自己的任务清单没问题但-u指定其他用户就需要 root 权限。如果报的是权限相关的提示加上sudo再试。实操心得把command -v当作排查命令找不到的第一条命令。它比which更符合 POSIX 规范能识别 shell 函数、别名和内置命令输出也更干净。我现在的习惯是任何脚本报command not found先在同一个 shell 里敲一遍command -v xxx能省掉大量猜测。5.2 /bin/bash^m: bad interpreter 是换行符在捣乱这个报错里那个^m特别扎眼它是回车符\r的可视化表示。文件在 Windows 下编辑保存时每一行结尾是\r\n两个字符而 Linux 只认\n一个。于是内核在解析 shebang 那一行时读到的实际内容是/bin/bash\r它去找一个名叫bash\r的解释器当然找不到于是报出这个错。确认方法很简单head -1 deploy.sh | cat -A如果输出是#!/bin/bash^M$那个^M就是元凶$表示行尾。修复有三种按场景选# 方案一就地替换最通用 sed -i s/\r$// deploy.sh # 方案二用专用工具适合批量处理 sudo apt install dos2unix dos2unix deploy.sh # 方案三用 tr 生成新文件不改原文件 tr -d \r deploy.sh deploy_fixed.sh chmod x deploy_fixed.sh如果你用 vim也可以在文件里执行:set ffunix再:wq:set ff会告诉你当前是dos还是unix这个命令我用了很多年比背参数省事。根本性的预防是在 Windows 上配置 Git 的换行符策略。装 Git for Windows 时那个Checkout Windows-style, commit Unix-style line endings的选项对应的就是core.autocrlftrue它在检出时把\n转成\r\n、提交时转回来很适合纯 Windows 开发环境。但如果你经常把脚本传到 Linux 服务器跑更推荐设成core.autocrlfinput只在提交时转换检出时保持原样git config --global core.autocrlf input项目根目录放一个.gitattributes文件更彻底可以按文件类型精细控制*.sh text eollf *.bat text eolcrlf *.png binary这样无论团队成员用什么系统脚本文件在仓库里永远存成 LF服务器拉下来直接能跑。5.3 Git Bash 安装时值得留意的几个选项在 Windows 上想要一个顺手的命令行环境Git Bash 是很多人的第一选择。安装过程本身不难但几个选项选错了会长期影响体验。下载安装包后一路下一步遇到选择默认编辑器时如果不熟悉 vim选 Notepad 或 VS Code 会让后续改配置文件舒服很多。遇到调整PATH环境变量的那一步三个选项对应三种策略只从 Git Bash 用、从命令行和第三方软件用、覆盖 Windows 自带的find和sort。推荐选中间那个既能在 CMD 和 PowerShell 里直接敲git又不会用 Unix 工具覆盖掉系统命令造成别的脚本出错。换行符那一页就是上一节说的core.autocrlf按你的实际使用场景选。终端模拟器那一页选 MinTTY它支持窗口缩放、复制粘贴快捷键更符合习惯。最后一项关于git pull默认行为的选默认或者 rebase 都行团队有规范就按规范来。装完之后有一个细节值得单独提MinTTY 环境下运行需要交互的程序比如 Python 的交互式解释器、某些需要读取键盘输入的命令时可能会遇到按键没反应的问题。这是因为 MinTTY 不是真正的 Windows 控制台。解决办法是给命令前面加winptywinpty python winpty mysql -u root -p新版本的 Git for Windows 已经在部分场景下自动处理了这个转换但遇到交互异常时加winpty依然是最快的验证手段。5.4 BASH 行编辑快捷键把命令行用成编辑器回到最初那个话题——BASH-like line editingGRUB 模仿的其实正是 GNU Readline 那套行编辑能力。这套快捷键值得系统性地记住因为它是通用的bash、Python 交互式解释器、MySQL 客户端、很多 REPL 环境都支持。快捷键作用Ctrl A光标跳到行首Ctrl E光标跳到行尾Ctrl U删除光标之前的所有内容Ctrl K删除光标之后的所有内容Ctrl W删除光标前的一个单词Ctrl Y粘贴上一次被删掉的内容Ctrl R反向搜索历史命令连按可继续往前找Ctrl L清屏内容还在只是滚上去了Alt B/Alt F按单词向前/向后移动光标Tab/Tab Tab补全连按两次列出所有候选最值得练熟的是Ctrl R。敲到一半发现命令输错了与其按几十次退格不如直接Ctrl R输入关键词历史里匹配的命令会浮出来按回车直接执行。另一个高频组合是Ctrl A加Ctrl K一键清空整行比长按退格快得多。如果想要更个性化的行为比如让补全忽略大小写、给常用命令加快捷键可以写~/.inputrcset completion-ignore-case on set show-all-if-ambiguous on \C-p: history-search-backward \C-n: history-search-forward第一行让cd down也能补全Downloads第二行让第一次按 TAB 就列出所有候选而不是等第二次后两行把Ctrl P和Ctrl N改成按已输入前缀搜索历史比默认的上一条下一条更精准。改完执行bind -f ~/.inputrc立即生效不用重开终端。习惯 vi 键位的人还可以在.bashrc里加一行set -o vi之后按 Esc 进入命令模式可以用h、l、w、b、dw这些操作来编辑命令行。用惯了 vim 的人会对这套键位爱不释手但代价是在其他不支持 vi 模式的 shell 里会条件反射地按错键。6. 常见问题速查表与我的实操心得6.1 GRUB 故障速查表现象最可能的原因排查动作处理方式grub rescue BASH-like 提示prefix 失效normal.mod 未加载ls逐个分区探测设 root/prefix 后insmod normalgrub但没有菜单grub.cfg 丢失或为空ls (root)/boot/grub手动 linux/initrd 启动后重建 cfginsmod normal报 file not foundprefix 层级写错ls确认路径里有 normal.mod修正 prefix注意 /boot 是否独立ls报 unknown filesystem文件系统损坏或缺模块用启动盘跑fsck修复文件系统或insmod ext2手动引导能进重启又挂配置里的 UUID 是旧的对比blkid与 fstab更新 fstab 并update-grubchroot 后 grub-install 报 canonical pathEFI 分区没挂载mount看挂载点挂载 EFI 分区后重试装完系统找不到启动项NVRAM 未写入efibootmgr -v重装或用--no-nvram后手动添加6.2 我在实际操作中积累的几条经验第一条动硬盘之前先备份/boot/grub/grub.cfg和/etc/fstab。这两份文件加起来不到 10KB用 U 盘拷一下或者传到自己的笔记里都行。但它们在故障时价值极高因为里面有正确的 UUID 和分区路径能让你五分钟定位问题而不是花两小时猜测。我现在给任何一台机器做分区调整前都会先把这两份文件留个副本。第二条修 GRUB 的时候别在 rescue 模式里折腾太久。手敲命令能进的系统说明问题在引导层手敲命令进不去的说明问题更深继续在 rescue 里试各种组合技纯属浪费时间。判断标准很简单如果你已经试了insmod normal和手动加载内核两条路还是进不去果断插启动盘。启动盘流程虽然步骤多但每一步都是确定的比在黑屏上盲猜快得多。第三条update-grub不是万能药。它只负责重新生成配置文件不会修复损坏的引导记录也不会修复 UUID 错乱。如果主板固件根本没找到引导项跑一百遍update-grub也没用必须走grub-install。这两个命令的关系我打个比方grub-install是把钥匙插到锁孔里update-grub是告诉钥匙这把锁对应的是哪扇门。钥匙没插上写再多门牌号也没意义。第四条虚拟机里复现一遍再动手。如果你对 GRUB 修复完全没经验可以在虚拟机里装一个系统、手动删掉/boot/grub目录、重启进入 rescue然后照着本文的步骤练一遍。这个过程花不了半小时但能在真实故障来临时给你极强的信心。我自己第一次遇到这个问题时是拿一台不重要的旧笔记本练的手第二次遇到时已经能闭着眼睛敲了。第五条关于换行符那类问题养成在服务器上只用 LF 的习惯。我现在的做法是本地开发时就把编辑器配成保存 shell 脚本用 LFGit 里放.gitattributes兜底服务器上再也不用为bad interpreter浪费时间。这种问题最讨厌的地方在于它不常出现所以每次出现都要重新搜索一遍答案把它一次性解决掉收益极高。最后一点小提醒如果你经常需要重装系统或者调整分区可以考虑把/boot做成独立分区。这样做的好处是重建引导时路径明确、不容易和其他系统混淆出问题时定位也更快。代价是要多规划一次分区大小一般给 1GB 到 2GB 足够装多个内核版本也不至于撑爆。这个取舍没有标准答案取决于你动硬盘的频率但至少值得在装系统前想一下。
返回列表