14

How can a bash script execute even after encountering a statement to delete itself? For eg when I ran test.sh script which conains:

<--some commands-->
rm test.sh
<--some more commands-->

end

The script executes till the end before deleting itself

CharlesB
  • 86,532
  • 28
  • 194
  • 218
user1004985
  • 2,573
  • 4
  • 19
  • 16
  • 3
    When an application is executed, its code is loaded into memory. You are just deleting the file on the disk, which does not affect the code in memory. – Felix Kling Oct 20 '11 at 10:37
  • 1
    Presumably the whole script is read into memory upon execution and so the commands after `rm test.sh` still exist in memory to be executed. – punkrockbuddyholly Oct 20 '11 at 10:38
  • It doesn't make a copy in memory. So, for example, if the script is modified while it's running, it will execute the modifications. This has been giving me a headache recently. Cute example: this one line script will fill up your disk in short order: 'cat $0 >>$0'. – Ned Mar 05 '14 at 18:11

2 Answers2

24

What actually happens is that bash keeps the file open and rm won't make that stop.

So rm calls the libc function "unlink()" which will remove the "link" to the inode from the directory it's in. This "link" is in fact a filename together with an inode number (you can see inode numbers with ls -i).

The inode exists for as long as programs have it open.

You can easily test this claim as follows:

$ echo read a> ni
$ bash ni

while in another window:

$ pgrep -lf bash\ ni
31662 bash ni
$ lsof -p 31662|grep ni
bash    31662 wmertens  255r   REG   14,2         7 12074052 /Users/wmertens/ni
$ rm ni
$ lsof -p 31662|grep ni
bash    31662 wmertens  255r   REG   14,2         7 12074052 /Users/wmertens/ni

The file is still opened even though you can no longer see it in ls. So it's not that bash read the whole file - it's just not really gone until bash is done with it.

w00t
  • 17,944
  • 8
  • 54
  • 62
  • 1
    This is why an update program should never change existing executable files, but rather unlink them, then rewrite the new version. – curiousguy Dec 02 '11 at 13:38
  • ok, but what happen if the file get overwritten by another process? The file is unlinked so it counts as "free-space", isn't it? – Gianluca Ghettini Jun 17 '14 at 13:37
  • @G_G overwriting just means that the directory entry named by the filename now links to another inode. As long as the original inode is not closed by bash, it will exist and will be used by bash. – w00t Jun 17 '14 at 15:40
-1

In fact, this phenomenon is specific to shells (like bash), which read the file into memory and then execute them.

If you execute the following a.bat: echo Yo1 del a.bat echo Yo2

You get the following output: C:>a.bat

C:>echo Yo1 Yo1

C:>del a.bat The batch file cannot be found.

This is per your expectation :-)

savinderpuri
  • 293
  • 1
  • 7
  • 1
    This is false; w00t's answer is correct. I have personally seen errors result when a bash script is *edited* while it is running, indicating that the file is being held open and read. – Kevin Reid Oct 21 '11 at 00:57