其实哪有什么“照着敲就行”。
全是骗鬼的。
每一个曾经撰写过Shell的人,心里都明晰,那些诸如if、for、case 的结构,看上去恰似小学阶段所学的英语内容,然而运行起来却犹如薛定谔的猫那般难以捉摸。
你压根不会知晓,它在下一个瞬间,会由于一个空格,或者一个未明确的变量,又或者一个可恶了的换行符,于凌晨三点之际,将你的传呼机弄成震动的模式。
刚入行那会儿,我特爱写判断用户是否存在的脚本。
身份标识用户名,并且其标准输出与标准错误流向空设备,否则命令无效,或者在这种情况下添加指定的用户名。
觉得自己聪明极了,一行搞定。
有那么一天,用户列表之中,躺着一个名为“root”的家伙,脚本居然一点儿没报错,可是,系统生生给我摆出了难看的脸色。
随后方才弄清楚,id 命令并非仅仅能够去查“具备状况”这么个情形,而且还能够去查“所具备状况的究竟是何物”。 句号。
在做饭之前,你需要去查看一下锅里是否存在已经变质变馊的剩饭,仅仅只有米是不行的事情,必须得是质量优良的好米才行呢。
那些if语句里的脏东西
最烦的是输入验证。
写个BMI计算器,高高兴兴等着用户输身高体重。
结果对面手一滑,输了个“abc”。
整个脚本就跟吃了死耗子一样,直接core dump。
后来,被迫去学,要用正则,去刮那一层层的皮,就是像这样的鬼画符:[[ $1 =~ ^[0-9]+.?[0-9]$ ]]。
就像超市扫码枪,扫不出来就“嘀嘀”报警,别让它进收银台。
case:别拿豆包不当干粮
有些人特轴。
让用户选yes/no,非得写三层if else。
我看着都累。
case这东西,不就是现成的多岔路口吗?
case $choice in
[Yy]|[Yy][Ee][Ss])
echo “您选了是”
[Nn]|[Nn][Oo])
echo “您选了否”
)
echo “您搁这儿打字谜呢?”
esac
你看,收银员不用记每个商品的价格,扫条码就行了。
for循环?
那是搬砖不带手套
文件名里有空格。
这事我说三遍。
想要写脚本去重命名文件,直接就采用 for file in *.log 这种方式,接着呢再运用 mv $file $file.bak。
跑完全部之后查看,有一种名为“a log”的文件,被硬生生拆分成为了“ a”以及“log”这两个文件,在这末尾的.bak都不清楚粘贴依附到哪一个之上了。
那感觉,就像搬砖没戴手套,手被碎瓷器划得血淋淋的。
之后变得机灵起来了,用双引号将其包裹住,或者运用C风格的for循环,起码内心会感觉安定一些。
while循环睡不睡觉,是个哲学问题
当年实习,写磁盘监控脚本。
while true; do
执行“df -h”命令,从中筛选出包含“/dev/sda1”的内容,将这些内容重定向输出到“/var/log/disk_alert”文件中。
done
没加sleep。
服务器的CPU,直接就被拉到了满负荷状态,情形酷似早高峰时段地铁里的那般状况,在其中把自身卡滞成为一个仿佛夹缝里艰难求存的职场上班族。
那负责运维的大哥过来瞧了瞧,然后丢下这么一句话:“你在挤地铁之前难道就不会等上两分钟绿灯嘛?”。
从此记住了:sleep 60 是续命良药。

break:走迷宫记得画记号
同事写猜数字游戏。
用户猜错了,他直接 break。
好家伙,循环是脱离了,然而用户连“猜错了”这样的提示都没能瞧见,进而还误以为程序处于死机状态了。
break这玩意儿,你得知道自己从几层楼跳。
break 2 才是从二楼蹦极,别拿跳楼机当滑梯用。
shift:左移多了,参数就丢了
处理命令行参数,shift 用得跟打麻将摸牌似的。
摸一张扔一张,扔着扔着发现手里没牌了。
关键参数丢了,脚本后面的逻辑全塌。
之后渐渐形成了习惯,每当进行一次shift操作的时候,就会使用echo $@去查看一下。
跟数钱似的,少一张都不行。
read+while:文件里藏着鬼
读 /etc/passwd,想按冒号切分。
结果手滑写成 IFS=‘,’。
整个屏幕上的用户名以及密码全部都串了顺序,root的那个shell变成了别人家中目录了下的/bin/false。
后来更换成了 cut,或者 awk,至少不会因为一个分隔符而将祖坟掘开了。
嵌套循环:画个流程图再动手
双重 for 循环生成 HTML。
里头随机字符串忘了加引号。
最后文件名长得跟乱码似的,浏览器打开直接404。
现今,在我进行复杂脚本书写之前,都会取来一张草稿纸,在上面画那么几下,起码以知晓电流朝着哪个方向行进,以免把保险丝给烧坏了。
版本号比较:Shell的智商洼地
真事儿。
在 GitHub 之上,存在着一个 Apache 项目,于该项目的脚本当中,进行着对 Java 版本的判断。
如果,当,‘$JAVA_VERSION’大于“1.9”这个情况出现时;那么。
结果装 OpenJDK 11 的机器,死活不进这个分支。
为啥?
由于Shell进行字符串比较遵循字典序,“11.0.27”的第二位是“1”,“1.9”的第二位是“.”,而在ASCII码中“.”比“1”小,故而Shell会认为11小于1.9。
那天 debug 到凌晨三点,想砸电脑。
后来老老实实提取主版本号,用 -gt 比数字。
空格、引号、换行符,全是刺客
于近期,OpenSSH出现了漏洞情况,此漏洞标识为CVE - 2025 - 61984。
攻击者在用户名里塞个换行符,就能绕过清理执行命令。
你提及 Shell 此物,历经数十年之久,至今仍在与换行符艰难进行智慧与勇气的较量。
写脚本写到这份上,哪还有什么“照着敲就行”。
都是些从坑中爬出来的人,他们一边拍打身上的土,一边对着你讲:要小心些,此地我才刚摔过跤呢。
系统不会同情你。
报错就是报错,卡壳就是卡壳。
改对了才能接着跑。
所以别再问我 Shell 脚本为啥老炸了。
要说也就是:空格没添引号,变量没开展判定,循环没进入休眠,break 跳错了层级结构。
跟生活一样,细节没卡准,整栋楼都给你歪了。

Comments NOTHING