标题: 在脚本运行时更新脚本文件,日本惠普误删77TB重要数据
时间: 2022-01-09发布,2022-01-09修改
转自 https://xw.qq.com/cmsid/20211230A00L9I00?f=newdc
作者:环球Tech
据京都大学主页的公报显示,本次数据丢失事件发生在 12 月 14 日 到 12 月 16 日之间,一共删除了/LARGE0 目录下的 3400 多万个文件,总容量大约 77 TB,其中有 49 TB 数据可以从备份恢复,28 TB 数据完全丢失。
具体事故的原因日本惠普也在 声明 PDF 中做了详细说明。
惠普用于超算系统的备份脚本会使用 find 命令找出无用的 Log 文件并删除,最近日本惠普为了提高程序的“可读性”对传给 find 命令的变量名做了一些修改,然后更新了系统中的脚本,但是没考虑到 Bash 会在运行过程中实时读取脚本文件然后执行,于是尚在执行中的备份程序读取了新脚本中的 find 指令,最终导致误删文件。
惠普日本在“谢罪声明”中表示对此次事件负全责,并承诺赔偿和善后。
编者记: Bash 在解析 Shell 脚本时,是边解析边执行的,并不是将脚本一次性读入内存后执行。如果脚本在执行时,我们用新脚本覆盖了旧脚本,而且文件的 inode 没有发生变化(比如使用 cp new.sh old.sh
,old.sh 内容变了,但 inode 不会变),那么 Bash 就会解析更新后的内容并执行。
老虎会游泳:在脚本运行时直接修改脚本文件,后果难以预料。
最好的情况是,修改后bash读取到的命令不合法,脚本报错退出。
但也有可能读取到的命令恰好合法,但传给命令的参数(变量)未正确设置(比如为旧脚本的值,或者旧脚本未设置该变量,值为空),此时会发生什么就完全不能预料了。
比如,日本惠普遇到的问题就是修改脚本后,正在运行的bash恰好读取到了find命令,但传给命令的路径参数为空(因为旧脚本没有设置对应变量),于是find列出了工作目录中的所有文件,然后这些文件被紧随其后的rm等命令删除。
『回复列表(17|隐藏机器人聊天)』
my.sh
被bash
打开,所以rm my.sh
并不会真正删除文件,只是把它隐藏了起来,bash
依然可以读取它。此后创建的新文件my.sh
和bash
正在读取的不是同一个文件。包管理器(比如dpkg
)更新软件包时应该都采用了先删后改的流程,你会看到xxx.new
被创建,然后再被重命名成旧文件。wget -O my.sh.new https://xxx.cn/my.sh
rm my.sh
mv my.sh.new my.sh
每次都使用不同的文件名,或者不同的目录,把版本号加在文件名里面。只要不涉及文件替换,就不会有此类问题。
先停止正在运行的进程,再修改。有风险,很可能会忘记停止,或者以为停止了但是由于某些原因未能停止。