Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
605 views
in Technique[技术] by (71.8m points)

bash - Can a shell script delete or overwrite itself?

#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?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.

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

Note that you get different results if you overwrite the 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

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

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

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

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

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 echo command, 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to MLink Developer Q&A Community for programmer and developer-Open, Learning and Share
...