想象一下:你每天早上要依次做十件琐事——拉开窗帘、烧水、浇花、喂猫、取报纸。刚开始你一件件亲手做,日子久了实在烦。于是你写了一张“晨间操作单”贴在墙上,机器人按单子逐条执行,你只管喝咖啡、看晨报。Bash 脚本就是这张“操作单”,终端就是你的机器人。你把平时反复敲的命令写进一个文件,加上判断和循环规则,之后只需一条命令,机器人就按清单把所有事情办妥。这张单子还支持“如果下雨就不浇花”的条件分支、“每个房间擦一遍”的循环、把整套动作打包成“快速指令”。本篇文章就从一张空白操作单开始,把 Bash 脚本的基础语法、变量与输入、条件循环、数组字符串、函数封装、调试规范一次讲透。学完之后你会发现,运维和部署中那些繁杂的重复工作,原来可以如此优雅地一键完成。
对 AI 从业者来说,Bash 脚本是连接数据、模型与服务器的“万能胶水”:批量清洗数据集、拉起训练任务、监控日志告警都靠它。掌握它,你的自动化能力会立刻上一个台阶,工作效率成倍提升。
可视化演示
展示Bash脚本的基础语法、条件循环和函数调试三个阶段,通过步进交互理解Shell脚本自动化执行的核心流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
基础语法执行 Shebang声明+变量赋值+echo输出 命令按顺序流式执行 $符号引用变量值
1. 脚本基础
给机器人写操作手册,第一件事就是让机器人知道“这是给我看的清单,按 Bash 的规矩来”。这张清单的开头必须有一行魔法文字 #!/bin/bash,它叫 shebang,意思是“请用 Bash 这个翻译官来读后面的内容”。没有这行字,系统可能把清单当成普通文本,或者用错解释器,就像你把中文菜谱递给一个只懂英文的厨师,他会一脸茫然。
写好清单后还要“盖章生效”——用 chmod +x 脚本名 给文件加上执行权限。这相当于在手册封面盖上“准许执行”的印章。没有印章,机器人虽然能读,但不敢动手。另外,手册里用 # 开头的内容是给人类看的备注,比如“这一步是备份数据库,别乱改”,机器人会安静地跳过它们。
手册执行到最后,机器人需要向你汇报“这次任务成功了吗”。它靠的是一个数字:退出状态码。返回 0 表示一切顺利,返回非 0 表示出了岔子。你可以在上一条命令结束后立刻用 echo $? 查看这个数字,就像机器人做完事向你比一个"OK"或摇摇手。
回到操作单的比喻:shebang 是手册的“语言声明”,chmod 是“执行印章”,注释是“给同事的便签”,退出码是“完成汇报”。四者构成了每一份合格操作手册的封面和结语。从此,你不再需要手动敲一串串命令,只需执行一个文件,机器人就按手册开干。
- 退出码变量
$?是 Bash 内置的特殊变量,永远保存上一条命令的退出码,像机器人额头上实时显示的表情。 - 成功与失败0 表示成功,非 0 表示失败;不同非 0 值还能区分不同错误原因。
2. 变量与输入
操作手册里总有一些会变的值:今天浇几盆花、喂几克猫粮、报纸放在哪个邮箱。你把它们写成“便签贴”贴在墙上,机器人执行时抬头看一眼便签就行。Bash 里的变量就是这张便签。赋值时直接写 name="Alice",注意等号两边不能有空格;要用它时写 $name 或 ${name},机器人会把便签内容替换进来。
有些便签是机器人自己带来的。当你在命令行运行 ./deploy.sh prod 时,脚本内部可以通过 $1 拿到 prod,$0 是脚本自己的名字,$@ 是全部参数,$# 是参数个数。这就像你递给机器人一张写着“目标环境:生产”的纸条,它一进家门就能从口袋里掏出来看。
如果手册需要现场询问主人,可以用 read 命令让机器人停下来等你回答,比如 read -p "请输入备份目录: " dir。而 export 可以把便签贴到全家共享的公告栏上,让机器人启动的其他子程序也能看见,这就是环境变量。
变量就像操作手册里那排可以随时撕换的便签:想改目标目录、改用户名、改重试次数,都不必重写整本手册,只换便签就行。配合 $1、read、export,手册既能接收外部指令,也能当面问你问题,变得灵活又聪明。
$ 符号触发“展开”:机器人读到 $name 时,会把便签上的内容替换进去,再拼出最终的话。- 变量赋值
name="Alice"把字符串 Alice 贴到名为 name 的便签上,等号两边不能有空格。 - 变量展开
${name}是展开语法,机器人把便签内容替换到当前位置。 - 结果拼接把展开后的内容与前后文本拼成完整问候语。
3. 条件判断
机器人不能只会埋头执行,还得学会“看情况办”。比如操作单上写着:如果下雨,就把晾在阳台的衣服收进屋里;如果出太阳,就继续晾晒。Bash 的 if 语句就是这种判断能力。它的骨架是:if 条件; then 做一件事; else 做另一件事; fi。fi 是 if 倒过来写,表示“判断结束”。
条件怎么写?常用 test 命令或方括号 [ ]。比如 [ "$age" -ge 18 ] 判断数字 age 是否大于等于 18;字符串比较用 = 或 ==;文件判断用 -f 文件(是不是普通文件)、-d 目录(是不是目录)。需要注意方括号里面每个元素之间必须有空格,[$age -ge 18] 会直接报错,就像把“如果下雨”写成“如果下雨”缺了空格,机器人就读不懂。
还有两个偷懒但很实用的写法:&& 表示“前面的成功了才做后面的”,|| 表示“前面的失败了就做后面的”。比如 mkdir backup && echo "创建成功",一行就完成了“先建目录,成功就报告”的逻辑。
操作手册从此有了“灵性”:备份目录不存在就自动创建,日志文件超过大小就压缩,GPU 空闲才启动训练。机器人不再是愣头青,而是会看天气收衣服的贴心管家。条件判断让脚本能应对真实世界千变万化的情况。
- 条件求值Bash 执行方括号内的表达式,得到真(退出码 0)或假(退出码非 0)。
- 真分支条件为真时,执行 then 后面的命令序列。
- 假分支条件为假时,执行 else 后的命令序列;没有 else 就什么都不做。
4. 循环控制
操作单上最烦人的一行是:“把 12 个房间的地板各擦一遍。”如果老老实实写 12 遍同样的命令,手册会又臭又长。聪明的做法是写一行:“对每个房间,执行擦地板。”Bash 的 for 循环就是这个意思:for room in 客厅 卧室 书房; do 擦地板 $room; done。机器人会挨个把元素取出来,循环执行 do 和 done 之间的命令。
除了 for,还有 while 循环:while [ 条件 ]; do ...; done,只要条件为真就反复执行,适合“没处理完就继续”的场景,比如等待某个进程退出。循环里有两个控制杆:break 是“立刻收工,后面的房间不擦了”;continue 是“这个房间跳过,下一个继续”。比如擦地板时发现杂物间上锁了,就 continue 跳过它。
循环最经典的用途是批量操作文件:for f in *.log; do gzip "$f"; done 会把当前目录下所有 .log 文件逐个压缩。一条命令,胜过手工敲几十遍。
循环是操作手册里最省力的“批量魔法”。一条 for 就能擦完所有房间、压缩所有日志、重命名所有图片。配合 break 和 continue,机器人还能在途中灵活应变,既不会死脑筋撞墙,也不会因为一个意外就撂挑子。
- 遍历起点循环变量 i 从 1 开始,对应第一个待处理元素。
- 累加处理每轮把当前处理的量累加到总数上,然后 i 加 1。
- 遍历终点直到 i 超过 n 时停止,此时所有元素都处理完毕。
5. 数组与字符串
擦地板时,你不会把 12 个房间的名字贴在 12 张便签上到处乱贴,而是准备一个收纳盒,每个格子编上号:1 号卧室、2 号书房、3 号杂物间。Bash 的数组就是这个收纳盒。定义很简单:rooms=(客厅 卧室 书房),取第 0 个格子用 ${rooms[0]},取全部格子用 ${rooms[@]}。
更高级的是关联数组,它不用编号而用名字做标签:declare -A cfg 后,cfg[host]="192.168.1.10" 就能按名字存取配置。这就像收纳盒的每个格子上贴着“主机地址”“端口号”这样的标签,找东西一目了然。
字符串处理也是脚本里的家常便饭。${s:0:5} 表示从第 0 个字符开始切 5 个字符;${s//旧/新} 表示把所有“旧”替换成“新”;${var:-默认值} 表示变量为空时用默认值兜底。这些写法都不需要调用外部命令,速度飞快。
数组和字符串处理让操作手册从“一张纸”升级成“带分类收纳柜的工作站”。房间清单、IP 列表、配置项都能各归其位。再配合字符串切片和默认值,处理文件名、解析配置、拼接路径都变得轻松利落,不用再调用 sed、awk 这些笨重工具。
- 下标索引方括号里的数字 i 指明“打开第几个格子”。
- 元素取值取出的值就是数组中第 i 个元素,可以赋值给变量或直接用。
- 整体展开
${array[@]}展开为所有元素,常配合 for 循环逐个处理。
6. 函数封装
你发现机器人每天要做三件事:开窗、浇花、喂猫。与其每次写三行命令,不如录一个组合技能叫“晨间流程”,以后一个口令就触发整套动作。Bash 函数就是这个“组合技能录制”。定义方式是 morning_routine() { 开窗; 浇花; 喂猫; },调用时直接写函数名即可。
函数也能接收参数,函数内部的 $1、$2 是传给函数的参数,跟脚本的位置参数互不干扰。比如 deploy() { echo "部署到 $1"; },调用 deploy prod 就会输出“部署到 prod”。函数里用 local 声明局部变量,比如 local ts=$(date +%s),这个变量只在函数内有效,不会污染全局,就像录技能时用的草稿纸,用完就收起来。
函数结束时用 return 返回状态码,0 表示成功,非 0 表示失败。这样调用方可以用 if deploy prod; then ... 判断部署是否成功。注意函数里的 return 只退出函数本身,不会退出整个脚本;想退出整个脚本要用 exit。
函数是把操作手册变薄的利器。晨间流程、部署流程、清理流程都被录成一个个“必杀技”,主脚本看起来就像一份目录,清晰好读。更重要的是,同样的技能可以在不同脚本里反复使用,真正实现“一次录制,到处播放”。
- 函数定义
func_name() { ... }定义函数,函数体放在大括号内。 - 参数传入调用时传入的值在函数体内通过 $1、$2 获取。
- 返回状态
return 0表示成功,return 1表示失败,供调用方判断。
7. 调试与严格模式
机器人也有出错的时候:浇花浇多了、擦地漏了角落。如果你不在现场,它可能一路错到底,把厨房淹了才停。Bash 给了你两样武器:安全锁和回放摄像头。安全锁就是 set -e,它让脚本在任何一个命令失败时立刻停下来,不再继续执行后面的危险操作。配合 set -u,用到没定义的变量就报错;配合 set -o pipefail,管道中任何一环失败都算整体失败。组合拳是 set -euxo pipefail,其中 -x 会逐行打印正在执行的命令,这就是回放摄像头。
调试时还可以用 bash -x script.sh 运行整个脚本,屏幕上会清楚显示每一步展开了什么、执行了什么。当脚本跑到第 30 行报错时,你回看摄像头记录,一眼就能定位是哪个变量没赋值、哪个文件路径写错了。
另一件法宝是 trap:它能在脚本收到信号或退出时执行清理动作。比如 trap 'rm -f /tmp/tmpfile' EXIT,保证即使脚本中途崩溃,临时文件也会被自动删除,像机器人摔倒前还会先把火关掉。
有了安全锁和回放摄像头,你再也不用提心吊胆地让机器人独自干活。就算出了岔子,它也会第一时间停下来向你报告,而不是带着错误一路狂奔。trap 更是给脚本上了最后一道保险,让意外退出也不留烂摊子。
- 执行命令脚本按顺序执行每一步操作。
- 检查状态
set -e让 Bash 自动检查上一条命令的退出码。 - 失败即停退出码非 0 时,脚本立即终止,避免连锁故障。
8. 实战规范
最后,一份大厨的操作手册和实习生的草稿本有什么区别?大厨的手册有固定格式:封面写菜名和用途,每步标清用量和时间,关键处有警告标记。Bash 脚本的最佳实践也一样。一个规范的脚本开头通常包括:#!/bin/bash、set -euo pipefail、脚本用途说明、用法示例、变量定义区,最后才是主逻辑。
命名规范也很重要:变量名用 snake_case 且语义清晰,比如 backup_dir 而不是 d;函数名用动词开头,比如 clean_temp_files。退出码要有约定:0 成功、1 通用错误、2 用法错误,这样调用方才能准确判断失败原因。
性能上有一个原则:尽量用 Bash 内置功能,少调用外部命令。内置的字符串处理和 for 循环比反复启动 grep、sed 快得多。批量处理一万个文件时,差距从“等几分钟”变成“眨眨眼”。
回到操作手册的比喻:规范不是束缚,而是让手册更可靠、更易维护的工程素养。一份结构清晰、命名讲究、退出码明确的脚本,三个月后你回头再看,依然能一眼读懂,就像大厨的菜谱传了三代也不会做砸。从今天开始,按规范写你的每一份 Bash “操作手册”吧。
- 内置操作时间Bash 内置语法(变量展开、循环)几乎零额外开销。
- 外部命令时间每调用一次外部命令都要 fork 子进程,开销大。
- 对比结论内置远快于外部,因此热点循环里应优先使用内置能力。
AI 应用场景
数据集的批量清洗与归档
阶段:数据准备
解决的问题:训练模型前,原始数据往往散落在几十个目录里,文件名混乱、格式不统一。手工一个个重命名、移动、去重,耗时且容易出错。Bash 脚本用 for 循环 + 条件判断 + 字符串处理,几分钟就能把整个数据集整理成规范目录结构。
具体案例:某算法工程师从标注平台下载了 2 万张图片,文件名带时间戳和乱码。他写了一个 Bash 脚本:按类别子目录遍历,用 ${name//[^a-z]/_} 清理非法字符,超过 500MB 的目录自动压缩归档,最后生成一份 manifest.csv 清单供训练脚本读取。
模型训练任务的一键拉起
阶段:训练运维
解决的问题:分布式训练需要在多台 GPU 服务器上同步启动、设置环境变量、检查显存、写日志。每次手动 ssh 到每台机器敲命令,效率低且容易漏步骤。Bash 脚本把整个流程封装成部署函数,一条命令拉起全部节点。
具体案例:某团队训练大模型时,使用一个 train.sh 脚本:先检查 nvidia-smi 确认显存充足,再用 for 循环 ssh 到每台工作节点启动训练进程,通过 trap 在训练异常退出时自动收集日志并通知群机器人。
训练日志监控与自动告警
阶段:模型监控
解决的问题:训练跑通只是开始,训练中途 loss 爆炸、GPU 掉卡才是噩梦。人不可能 24 小时盯着日志。通过 cron 定时任务配合 Bash 脚本,可以定期扫描日志中的 loss 值,超过阈值就发告警。
具体案例:某工程师写了一个监控脚本,用 while 循环每隔 10 分钟读取训练日志的最后一行,用 grep 提取 loss 数值,与阈值比较;异常时调用 webhook 发送企业微信告警,同时用 set -e 和 trap 保证脚本自身稳定运行。
Python 演示
#!/usr/bin/env python3# bulk_clean.py : 批量清理超过阈值的日志文件import osimport sysimport time BACKUP_DIR = "backup"MAX_SIZE = 1024 * 1024 # 超过1MB的文件需要归档 def log(msg): print("[%s] %s" % (time.strftime("%H:%M:%S"), msg)) def clean_file(path): """处理单个文件,返回处理结果。""" if os.path.getsize(path) <= MAX_SIZE: return "skip" target = os.path.join(BACKUP_DIR, os.path.basename(path)) if "--dry-run" in sys.argv: return "plan" os.rename(path, target) return "done" def main(): if not os.path.exists(BACKUP_DIR): os.makedirs(BACKUP_DIR) targets = sys.argv[1:] if not targets: log("usage: python3 bulk_clean.py <dir> [dir2 ...]") return 2 files = [] for d in targets: for name in os.listdir(d): if name.endswith(".log"): files.append(os.path.join(d, name)) stats = {"done": 0, "plan": 0, "skip": 0} for path in files: result = clean_file(path) stats[result] += 1 log("%s -> %s" % (path, result)) log("summary: done=%d plan=%d skip=%d" % ( stats["done"], stats["plan"], stats["skip"])) return 0 if __name__ == "__main__": sys.exit(main())
if not targets:没有传入目录参数时输出用法并返回退出码 2,对应 Bash 的usage()习惯。for name in os.listdir(d):遍历目录下的每个文件名,对应 Bash 的for f in *.log。if name.endswith(".log"):只收集后缀为 .log 的文件,相当于 Bash 里的文件名通配过滤。files.append(os.path.join(d, name))拼出完整路径,相当于 Bash 里"$d/$name"的路径拼接。result = clean_file(path)把单个文件的处理逻辑封装成函数,对应 Bash 函数封装思想。if os.path.getsize(path) <= MAX_SIZE:大小判断条件,对应 Bash 里[ size -le MAX ]的条件判断。if "--dry-run" in sys.argv:解析命令行参数做模拟运行,相当于 Bash 脚本中检查$1是否为--dry-run。stats[result] += 1用字典统计各结果数量,对应 Bash 里用变量累加计数。sys.exit(main())把 main 的返回值作为脚本退出码,对应 Bash 的exit 0约定。
常见误区
误区我刚开始学 Bash 时,很自然地写下 `name = "Tom"`,心想这不是和 Python、JavaScript 一样嘛,等号两边加空格看起来更整齐,结果终端报错 `command not found`,我一脸懵。
正解Bash 对空格极度敏感。name = "Tom" 会被解析成“执行一个叫 name 的命令,参数是 = 和 Tom”。正确写法是 name="Tom",等号两侧都不能有空格。这就像写操作手册时,机器人把每个词都当成独立的指令,多一个空格就多一个词,指令就变味了。
为何常见:因为大部分现代编程语言都允许赋值语句带空格,Bash 这种“空格即分隔符”的设计对新手很反直觉。
误区我写 `for f in *.log; do rm $f; done`,心想这不挺好吗。结果文件名里有个 `my notes.log`,rm 收到两个参数 `my` 和 `notes.log`,直接报错。
正解Bash 在展开 $f 后不会自动重新分词,但展开结果如果包含空格或通配符,会被当成多个词处理。稳妥做法是始终写 "$f",让展开结果作为一个整体传给命令。好比机器人听到“擦地板卧室书房”会拆成两件事,你加上引号“擦地板卧室书房”,它就知道这是一件事的名字。
为何常见:因为在命令行交互时很少遇到带空格的文件名,写脚本时容易忽略这个差异,直到线上炸了才想起来。
误区我加了 `set -e` 后觉得万事大吉,脚本再也不会带错跑下去了。可后来某个命令明明失败了,脚本却继续执行,我怀疑 set -e 是假的。
正解set -e 不是万能的。它的失效场景包括:管道中只有最后一个命令的退出码被检查(除非加 set -o pipefail)、条件判断 if 里的命令失败不计、前面带 ! 的命令失败不计。所以严格模式要写成 set -euxo pipefail 组合拳,相当于给机器人上了全套保险而不是只锁一道门。
为何常见:set -e 的名字太有迷惑性,让人误以为它是“脚本永不犯错”的开关,而没意识到它只是一条有边界的规则。
误区我在函数里写了 `exit 1` 表示“这个环节出错了”,结果函数一调用,整个脚本直接没了,后面的清理步骤全没执行。
正解exit 是“整个脚本结束”,return 才是“退出当前函数”。函数内想表示失败应该用 return 1,把状态码交给调用方决定怎么处理。这就像机器人执行“晨间流程”时,浇花环节发现花洒坏了,它应该停下这个环节向主人报告,而不是直接把整栋房子的电闸拉了。
为何常见:exit 和 return 在别的语言里语义差别很大,新手容易把“退出当前逻辑”和“终止整个程序”混为一谈。
误区我写 `[ "$num" == "10" ]` 判断数字大小,结果 num=9 时它却说成立,我完全想不通。
正解== 和 = 比较的是字符串内容,不是数值大小。"9" == "10" 在字符串层面当然不相等,但如果你比较 "10" == "10" 那只是巧合。数值比较要用 -eq(等于)、-ne(不等)、-gt(大于)、-lt(小于)。这就像机器人分不清“编号 9”和“数值 10 谁大”,你让它比大小得用尺子(-gt),而不是比标签文字(==)。
为何常见:几乎所有现代语言里 == 都能做数值比较,Bash 却把字符串和数值比较分成了两套运算符,这是 Shell 历史设计留下的坑。
面试题
Q1. #!/bin/bash 这一行在脚本中的作用是什么?
- A.声明脚本文件的编码格式
- B.指定解释器执行脚本← 正确答案
- C.给脚本添加执行权限
- D.输出脚本运行的日志
答案:B。shebang 行告诉操作系统用哪个解释器来执行这个脚本。编码格式由文件本身决定,执行权限靠 chmod,日志靠 echo,所以只有 B 正确。这就像在操作手册封面写明“请用 Bash 翻译官阅读本手册”。
Q2. 执行 chmod +x run.sh 后,会带来什么变化?
- A.脚本运行速度变得更快
- B.脚本文件内容会被加密
- C.脚本获得可执行权限← 正确答案
- D.脚本自动修复语法错误
答案:C。chmod +x 是给文件加上“可执行”权限,相当于在操作手册上盖了“准许执行”的章。它不改变内容、不加快速度、也不修 bug,只是让系统允许直接运行这个文件。
Q3. 下面哪条是 Bash 变量赋值的正确写法?
- A.
name = "Tom" - B.
name="Tom"← 正确答案 - C.
$name="Tom" - D.
name<-"Tom"
答案:B。Bash 变量赋值要求等号两侧不能有空格,所以 B 正确。A 会被解析成执行 name 命令,C 把 $ 放错了位置,D 的箭头写法在 Bash 里不是赋值语法。记住:便签贴要紧紧贴在盒子上,不能留缝隙。
Q4. 在脚本中执行 echo $? 会立刻输出什么信息?
- A.当前脚本执行的行数
- B.上条命令的退出状态码← 正确答案
- C.当前用户的用户编号
- D.上条命令的最终输出
答案:B。$? 是 Bash 的特殊变量,保存上一条命令的退出码:0 成功、非 0 失败。它不是行号、不是用户 ID、也不是命令输出。就像机器人额头上的表情,实时反映刚才那件事办得怎么样。
Q5. 判断变量 a 的数值是否大于 b,下面哪个写法正确?
- A.
[ $a > $b ] - B.
[ $a -gt $b ]← 正确答案 - C.
[ $a == $b ] - D.
if $a > $b
答案:B。数值比较必须用 -gt(大于)、-lt(小于)、-eq(等于)等运算符,B 正确。A 里的 > 在方括号里会被当成输出重定向,C 的 == 是字符串比较,D 的 if 语法根本不对。数值比大小要用尺子,不能用比标签的方式。
Q6. 执行 for f in *.txt; do echo "$f"; done 会输出什么?
- A.把所有文件名打印成一行
- B.逐个输出每个 txt 文件名← 正确答案
- C.只输出第一个 txt 文件名
- D.统计 txt 文件的总数量
答案:B。for 循环把当前目录下匹配 *.txt 的每个文件名依次赋给 f,然后分别执行 echo,所以是逐个分行输出。就像机器人挨个房间擦地板,每个房间单独报告。它不统计数量,也不合并打印。
Q7. set -e 在 Bash 脚本中的核心作用是什么?
- A.每次运行结束后自动退出终端
- B.某条命令失败时立即停止脚本← 正确答案
- C.提升脚本整体的执行效率
- D.隐藏脚本产生的错误输出
答案:B。set -e 让脚本在任意命令返回非 0 退出码时立刻终止,避免带着错误继续执行。它不退出终端、不加速、不屏蔽输出。相当于给机器人装了“出错即停”的安全锁,防止厨房被淹了还在继续浇花。
Q8. 关于 Bash 函数中的 return 和脚本的 exit,下列说法正确的有哪些?
- A.return 只退出当前函数← 正确答案
- B.exit 会结束整个脚本进程← 正确答案
- C.return 和 exit 可以互换使用
- D.return 可以携带状态码返回← 正确答案
答案:ABD。return 退出当前函数并返回状态码,供调用方判断;exit 终止整个脚本进程,一般用于脚本收尾。两者作用范围完全不同,不能互换,所以 C 错误。就像机器人录制的“组合技能”中途停下与整个机器人关机断电是两码事。
Q9. 关于 set -euxo pipefail 这一组合,下列说法正确的有哪些?
- A.
-e让脚本在出错时立即停止← 正确答案 - B.
-x会逐行打印执行的命令← 正确答案 - C.
-u使用未定义变量就报错← 正确答案 - D.
pipefail只看管道最后一个命令
答案:ABC。-e 出错即停,-x 打印执行痕迹,-u 杜绝未定义变量,这些都是正确描述。pipefail 恰恰相反:它让管道中任何一个命令失败都导致整体失败,而不是只看最后一条,所以 D 错误。这四件套组合起来才是完整的“安全锁 + 回放摄像头”。
Q10. 关于脚本中的 trap 命令,下列说法正确的有哪些?
- A.可以在脚本退出前执行清理动作← 正确答案
- B.可以捕获并忽略 SIGKILL 信号
- C.常用于删除临时文件和回收资源← 正确答案
- D.可以捕获 Ctrl-C 中断信号← 正确答案
答案:ACD。trap 可以在收到信号或 EXIT 时执行清理,比如删除临时文件、关闭连接,A 和 C 正确。Ctrl-C 对应 SIGINT 信号,也可以被 trap 捕获,D 正确。但 SIGKILL(强杀)无法被任何进程捕获处理,B 错误。trap 就像机器人摔倒前先伸手关掉煤气灶的安全网。