bash shell 脚本可以删除或覆盖自身吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20722064/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:03:31  来源:igfitidea点击:

Can a shell script delete or overwrite itself?

bash

提问by Paolo

#beginning of bashscript1.sh
source bashscript2.sh
echo $variable

and here is the source file:

这是源文件:

#beginning of bashscript2.sh
rm -f bashscript2.sh
variable = "integer of some kind"

How will the bash script be handled? Does it first load the source file and then deletes it, or will the variable have a value in bash script 1?

bash 脚本将如何处理?它是先加载源文件然后删除它,还是该变量在 bash 脚本 1 中有一个值?

回答by

On Unix-like operating systems, removing a file is possible if it is still open. The file name will no longer exist, but the data itself does remain, and any programs that have an open handle, including bash, can continue to read (and even write) using that handle. Only when the last program closes its handle does the file really get deleted.

在类 Unix 操作系统上,如果文件仍处于打开状态,则可以将其删除。文件名将不再存在,但数据本身仍然存在,任何具有打开句柄的程序,包括 bash,都可以使用该句柄继续读取(甚至写入)。只有当最后一个程序关闭其句柄时,文件才会真正被删除。

So, in a sense, yes, a shell script can delete itself, but it won't reallybe deleted until after the execution of that script finishes.

所以,从某种意义上说,是的,shell 脚本可以删除自身,但在该脚本执行完成之前它不会被真正删除。

Note that you get different results if you overwritethe file instead of deleting it. Shells may (and do) use buffering to avoid reading one byte at a time, but the buffer has a finite size. If the file contents change beyond what the shell has already read into memory, it will see the new content. You can create a simple example of this if you examine what the buffer size for your system is. On my system, it happens to be 8 KiB. So a shell script that contains

请注意,如果覆盖文件而不是删除文件,则会得到不同的结果。Shell 可能(并且确实)使用缓冲来避免一次读取一个字节,但缓冲区的大小是有限的。如果文件内容的变化超出了 shell 已经读入内存的内容,它将看到新的内容。如果您检查系统的缓冲区大小,您可以创建一个简单的示例。在我的系统上,它恰好是 8 KiB。所以一个shell脚本包含

echo line 1
>test.sh
# (8167 random characters)
echo line 4

so the second block of data is "cho line 4", on my system, outputs

所以第二个数据块是“ cho line 4”,在我的系统上,输出

$ bash test.sh
line 1
test.sh: line 4: e: command not found

because the ehas already been read, and the shell encountered EOF when trying to read the rest of the line.

因为e已经被读取,并且 shell 在尝试读取该行的其余部分时遇到了 EOF。

Update: rici shows that with a different example of overwriting the file, the newly written contents do get used. Reworking that:

更新:rici 显示,通过覆盖文件的不同示例,新写入的内容确实得到了使用。返工:

script="`tr 12 21 <test.sh`"
env echo "$script" >test.sh
echo toggle: 1

The second line intentionally doesn't use bash's built-in echocommand, because that sometimes doesn't cause bash to re-read the script, per the comments, but precisely when it does and doesn't is unclear to me. bash outputs the newly written toggle value when it gets to line three. The relevant difference between this and my earlier example seems to be that here, bash can seek to the current position when it gets to line three, whereas in my earlier example, that is impossible, because that position no longer exists, as the file is empty.

第二行故意不使用 bash 的内置echo命令,因为根据评论,这有时不会导致 bash 重新读取脚本,但确切地说,它何时执行,何时执行,我不清楚。bash 在到达第三行时输出新写入的切换值。这与我之前的示例之间的相关区别似乎在于,这里 bash 可以在到达第三行时寻找当前位置,而在我之前的示例中,这是不可能的,因为该位置不再存在,因为文件是空的。

回答by elnigno

Is this a curiosity you have or what you actually want to obtain?

这是你的好奇心还是你真正想要得到的?

Anyway, I've tried myself this simple script (test_script.sh):

无论如何,我已经尝试过这个简单的脚本(test_script.sh):

rm -f test_script.sh
echo "Still here!"

and it prints Still here!, so the file was loaded before execution. Execution is not possible the second time.

并打印Still here!,因此文件在执行前已加载。第二次执行是不可能的。

To answer your question, yes and no. The commands in the script are loaded and executed, and can delete the source file of the script. This will make impossible to execute the same file again, of course, but will not affect the first execution.

回答你的问题,是和否。脚本中的命令被加载和执行,并且可以删除脚本的源文件。这当然会使同一个文件无法再次执行,但不会影响第一次执行。