编辑bash脚本时要小心

假设我写了一个名为的bash脚本delay.sh你觉得他做什么?

#!/bin/bash
sleep 30
#rm -rf --no-preserve-root /
echo "Time's up!"

似乎等待30秒,然后在屏幕上显示一条消息。这里没有技巧-他只是这样做。中间有一个危险的命令,但已将其注释掉并且不执行。

想象一下我再次运行此脚本,但是现在我不想等待30秒-这太长了。我打开第二个控制台,更改sleep 30sleep 3,然后保存文件。您认为现在会发生什么?

好吧,在30秒后,脚本将删除我的所有文件。

这是因为bash在脚本执行过程中会按片段读取脚本的内容,并以字节为单位跟踪偏移量。当我从字符串中删除一个字符sleep,偏移下一个命令点到开始r#rm,而不是#从解释器的角度来看,它#已移至上一行,因此它执行从开始的命令rm

可以通过观察Linux上的bash系统调用来确认。这是问题strace bash delay.sh,带有注释和缩写。

#  
openat(AT_FDCWD, "delay.sh", O_RDONLY)  = 3

#    ( 80 )
read(3, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 80) = 64

#   
lseek(3, 0, SEEK_SET)                   = 0

#      255
dup2(3, 255)                            = 255

#  64-  ,   
read(255, "#!/bin/bash\nsleep 30\n#echo \"Don'"..., 64) = 64

#      ,    
# Offset 21 is the `#`
lseek(255, -43, SEEK_CUR)               = 21

#  ,   sleep
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2072

#   wait4    `30`  `3`

#  64-  ,    
#         echo
read(255, "echo \"Don't execute me\"\necho \"Ti"..., 64) = 42

# Bash    echo    
# , -   
write(1, "Don't execute me\n", 17)      = 17
write(1, "Time's up!\n", 11)            = 11

#       
read(255, "", 64)                       = 0

因此,在开始编辑当前正在运行的bash脚本时要小心他可能执行了错误的命令或执行了一些非常意外的事情。

All Articles