我注意到有时循环的 bash 脚本似乎被加载到内存中,但有时它似乎继续从磁盘读取它。对于一个不平凡的脚本,我无法弄清楚其中哪一个会发生。
通常这在实践中并不重要,但是如果我对脚本进行更改,有时(但似乎并不总是)当我保存更改时,正在运行的脚本会被破坏,因为显然它是从脚本中的特定点读取的文件和事情已经不再是他们离开时的样子了!
所以我只是想问:有没有办法知道脚本是否不断地从磁盘读取而不是从内存执行?
像这样的简单脚本似乎完全从内存中读入并执行,因为更改abc
和xyz
保存不会影响脚本的运行实例:
#!/usr/bin/env bash
while :
do
echo abc
sleep 2
done
也许这只是尺寸问题?
答案1
这在一定程度上是一个尺寸问题。当从常规文件中读取时,Bash 一次读取一个块,类似于 C 库的做法,一次可能读取几千字节。然后它解析它得到的所有完整行,并执行任何完全的命令它有。但它也会将读指针返回到它离开的位置,因此即使文件很小,它也可能会看到对文件的修改。 (不过,它似乎并不总是向后查找。我不确定它是否只在运行外部命令时才这样做。)
所以,如果你有这个:
echo one
sleep 123
# filler if needed
echo two
并且您在睡眠期间就地编辑该文件,您也许可以echo
在 Bash 读取并运行它之前修改第二个文件。其他一些 shell(如 Dash 或 Busybox)不会向后查找读指针,因此只有在命令之间有一个大的、多 kB 的填充符时,您才会获得效果。
但是,如果你有
main() {
echo one
sleep 123
# really long multi-kB comment
# ...
echo two
}
main
shell 会一次性读取并存储该函数,然后从内存中运行它。
还有一个成语叫“有”
main "$@"; exit
作为文件的最后一行。由于 Bash 会立即读取并解析整行,因此这可以确保 shell 在 main 函数之后退出,即使文件随后被修改。
好像我之前写过另一个答案,在下面运行时替换 shell 脚本。那里有一个自修改脚本的示例。