gpt4 book ai didi

Bash 对运行脚本的更改差异

转载 作者:行者123 更新时间:2023-12-05 01:50:21 25 4
gpt4 key购买 nike

在编辑正在运行的脚本时,我对 bash 的两种看似不同的行为感到困惑。

这里不是讨论为什么要这样做的地方(您可能不应该这样做)。我只想尝试了解会发生什么以及为什么。

示例 A:

$ echo "echo 'echo hi' >> script.sh" > script.sh
$ cat script.sh
echo 'echo hi' >> script.sh
$ chmod +x script.sh
$ ./script.sh
hi
$ cat script.sh
echo 'echo hi' >> script.sh
echo hi

脚本自行编辑,并直接执行更改(额外的回显行)。多次执行会导致更多行的“hi”。

示例 B:

创建一个脚本 infLoop.sh 并运行它。

$ cat infLoop.sh
while true
do
x=1
echo $x
done
$ ./infLoop.sh
1
1
1
...

现在打开第二个 shell 并编辑文件,更改 x 的值。例如。像这样:

$ sed --in-place 's/x=1/x=2/' infLoop.sh
$ cat infLoop.sh
while true
do
x=2
echo $x
done

然而,我们观察到第一个终端的输出仍然是1。只用一个终端做同样的事情,通过 Ctrl+Z 中断 infLoop.sh,编辑,然后通过 fg 继续它会产生相同的结果.

问题

为什么示例 A 中的更改立即生效,而示例 B 中的更改却没有?

PS:我知道那里有显示类似示例的问题,但我看到的这些问题都没有解释场景之间差异的答案。

最佳答案

实际上有两个不同的原因导致示例B不同,其中任何一个都足以阻止更改生效。它们是由于 sedbash 如何与文件交互(以及类 unix 操作系统如何处理文件)的一些微妙之处,并且可能因程序略有不同而有所不同,等等

总的来说,我想说这是一个很好的例子,说明理解和预测如果你在运行文件(或从中读取等)的同时修改文件会发生什么是多么困难,因此它为什么不好想法做这样的事情。基本上,它相当于 sawing off the branch you're standing on 的计算机.

原因 1:尽管选项名称如此,sed --in-place 实际上并没有就地修改现有文件。它实际上所做的是创建一个具有临时名称的新文件,然后在完成后删除原始文件并将新文件重命名到它的位置。它具有相同的名称,但实际上不是同一个文件。您可以通过使用 ls -li 查看文件的 inode 编号来判断:

$ ls -li infLoop.sh 
88 -rwxr-xr-x 1 pi pi 39 Aug 4 22:04 infLoop.sh
$ sed --in-place 's/x=1/x=2/' infLoop.sh
$ ls -li infLoop.sh
4073 -rwxr-xr-x 1 pi pi 39 Aug 4 22:05 infLoop.sh

但 bash 仍然打开旧文件(严格来说,它有一个指向旧文件的打开文件句柄),因此无论新文件发生什么变化,它都会继续获取旧内容。

请注意,这并不适用于所有编辑文件的程序。例如,vim 将重写现有文件的内容(除非文件权限禁止它,在这种情况下它会切换到 delete&replace 方法)。使用 >>> 附加将始终附加到现有文件而不是创建新文件。

(顺便说一句,如果 bash 在文件被“删除”后打开它似乎很奇怪,那只是类 unix 操作系统处理其文件的方式的一部分。文件在删除最后一个目录条目之前不会真正删除 < strong>和引用它们的最后一个打开的文件句柄被关闭。一些程序实际上通过打开(/创建)一个文件然后立即“删除”它来利用这一点来提高安全性,因此打开的文件句柄是访问文件的唯一方法。)

原因 2:即使您使用的工具实际修改了现有文件,bash 仍然看不到更改。这样做的原因是 bash 从文件中读取(边读边解析)直到它有可以执行的东西,运行它,然后返回并读取更多直到它有另一个可执行 block ,等等。它不会返回并重新-读取相同的 block 以查看它是否已更改,因此它只会注意到它尚未读取的文件部分的更改。

在示例 B 中,它必须读取并解析整个 while true ... done 循环才能开始执行它。因此,一旦循环被读取并开始执行,该部分(或可能之前)的更改将不会被注意到。循环退出后 文件中的更改将在循环退出后被注意到(如果曾经退出的话)。

请参阅我对 this question 的回答(以及 Don Hatch 对此的评论)了解更多相关信息。

关于Bash 对运行脚本的更改差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73244314/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com