Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwrite executing bash script files

Tags:

bash

What will happen if the executing bash script file is overwritten? Will it continue execute the old file or overwritten file ?

For example /etc/test.sh has the following contents

cp /test.sh /etc/test.sh

like image 321
user3190975 Avatar asked Dec 20 '22 19:12

user3190975


1 Answers

bash generally does not load the entire script in advance, so overwriting the script can have unpredictable consequences. For example, I just created a script containing this:

#!/bin/bash
echo start old file
sleep 20
echo end old file

...and ran it. While it was sleeping, I overwrote it with this slightly different script:

#!/bin/bash
echo started new file
sleep 20
echo end new file

Resulting in this output:

$ ./test.sh 
start old file
./test.sh: line 4: 0: command not found
end new file

What happened was that bash had read through the "sleep 20\n" line (including the line terminating newline) before sleeping. When it continued after that, it read the next command from the next byte position in the file, and since the second line had gotten two bytes longer ("start" -> "started"), it wound up reading the last two bytes of the new sleep line ("sleep 20\n" -> "0\n"), trying to execute "0" as a command, and getting an error. It then runs the final line of the new contents. Pretty messy, right?

Fortunately, there's a way to force bash to load the entire script into memory so it won't get confused if it gets changed while running:

#!/bin/bash
{
    echo start old file
    sleep 20
    echo end old file
    exit
}

The { forces the shell to read at least through the matching } in order to properly parse the command, and the exit then makes sure it'll never try to execute anything that gets added after that }.

BTW, I was testing this with bash version 3.2.48(1)-release (on OS X 10.8.5); other versions may behave differently...

UPDATE: Other versions do indeed behave differently. I tried the same test with version 4.3.0(1)-release (under NetBSD 6.1.4), and it continued to run the old code after the file's contents had been replaced. Apparently it now buffers the file in 8KB blocks (see this unix.se answer).

like image 81
Gordon Davisson Avatar answered Jan 06 '23 22:01

Gordon Davisson