假设我写了一个名为的bash脚本delay.sh
。你觉得他做什么?#!/bin/bash
sleep 30
echo "Time's up!"
似乎等待30秒,然后在屏幕上显示一条消息。这里没有技巧-他只是这样做。中间有一个危险的命令,但已将其注释掉并且不执行。想象一下我再次运行此脚本,但是现在我不想等待30秒-这太长了。我打开第二个控制台,更改sleep 30
为sleep 3
,然后保存文件。您认为现在会发生什么?好吧,在30秒后,脚本将删除我的所有文件。这是因为bash在脚本执行过程中会按片段读取脚本的内容,并以字节为单位跟踪偏移量。当我从字符串中删除一个字符sleep
,偏移下一个命令点到开始r
的#rm
,而不是#
。从解释器的角度来看,它#
已移至上一行,因此它执行从开始的命令rm
。可以通过观察Linux上的bash系统调用来确认。这是问题strace bash delay.sh
,带有注释和缩写。
openat(AT_FDCWD, "delay.sh", O_RDONLY) = 3
read(3, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 80) = 64
lseek(3, 0, SEEK_SET) = 0
dup2(3, 255) = 255
read(255, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 64) = 64
lseek(255, -43, SEEK_CUR) = 21
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2072
read(255, "echo \"Don't execute me\"\necho \"Ti"..., 64) = 42
write(1, "Don't execute me\n", 17) = 17
write(1, "Time's up!\n", 11) = 11
read(255, "", 64) = 0
因此,在开始编辑当前正在运行的bash脚本时要小心。他可能执行了错误的命令或执行了一些非常意外的事情。