Overwrite the execution of bash script files

What happens if the bash script executable is overwritten? Will it continue to execute the old file or overwritten file?

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

cp / test.sh / etc / test.sh

+1
bash
source share
2 answers

bash usually does not load the entire script in advance, so rewriting 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 launched it. While he was sleeping, I overwrote it with a slightly different script:

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

Resulting result:

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

It so happened that bash read the line "sleep 20 \ n" (including the line ending a new line) before going to bed. When he continued after that, he read the next command from the next byte position in the file, and since the second line received two bytes longer ("start" → "start"), she finished reading the last two bytes with a new sleep line ("sleep 20 \ n "→" 0 \ n "), trying to execute the" 0 "command as a command and get an error message. Then it launches the last line of new content. Pretty dirty, right?

Fortunately, there is a way to get bash to load the entire script into memory so that it doesn't get confused if it changes during runtime:

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

{ forces the shell to read at least through matching } to correctly parse this command, and exit will then make sure that it never tries to execute anything added after that } .

By the way, I tested this with bash version 3.2.48 (1) -release (on OS X 10.8.5); other versions may behave differently ...

UPDATE: Other versions do 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 replacing the contents of the file. Apparently, it is now buffering the file in 8KB blocks (see this unix.se answer ).

+6
source share

The shell loads the script into memory and creates a separate process, so the old script will continue to work unchanged.

Obviously, if you try to restart it, you will get a new version.

If you are trying to introduce some new features at runtime, I would suggest writing to a temporary file and then executing that file using the $() or `` (backtick) syntax to create a new process.

Alternatively, you can use exec to completely replace the current program.

+1
source share

All Articles