42

Suppose I have a script script.sh, which takes some time to execute. I execute it, ./script.sh. While it is running in a terminal window, I modify the file script.sh. Will this have any effect on the already running process?

After modifying it, I execute the modified file, so I have two running process now. Is this okay?

1

5 Answers 5

47

When you make changes to your script, you make the changes on the disk(hard disk- the permanent storage); when you execute the script, the script is loaded to your memory(RAM).

So, the changes that you make to the script will not affect the running script, it will run the version you executed before making those changes.

However, when you execute the changed script again without terminating the previously running instance, there will be two instances of the script- one which has the changes and the old one.

Be warned that the resources that the script uses and modifies will conflict. For example, if you are modifying a file using the script, the script that runs later will not be able to open that file for writing and fail to execute correctly.

Update: Thanks to Registered User for pointing me to a better answer on Unix.stackexchange.com.

Depending upon the size of the script and the compiler/interpreter in question, the script is loaded partially/completely. So, if the script is not completely loaded, the changes that you make to your script will reflect on the running instance once the part of the script is loaded into memory.

So, it is not recommended to change your script on the disk which is currently running for unpredictable output: First stop the running instance and then modify your script and then re-execute the script.

8
  • 16
    Not the perfect answer, read unix.stackexchange.com/q/121013/55673 Jun 16, 2014 at 14:30
  • 1
    @registereduser: oh yes, that question just reminded me of my OS lessons. Will edit my answer as soon as i get my hands on to my desktop (on my phone right now)
    – jobin
    Jun 16, 2014 at 14:38
  • I guess that for short scripts there should be no problem.
    – becko
    Jun 16, 2014 at 15:49
  • 1
    When I tried this with bash v3.2.48 (see here), it didn't buffer beyond the end of the line (and failed badly when I modified the script as it executed). I just retested with bash v4.3.0, and it buffered the entire (short) script. So... I wouldn't count on any particular behavior. Jun 17, 2014 at 2:45
  • 1
    @RegisteredUser Not with all versions of bash -- see the example I linked. Jun 17, 2014 at 5:04
11

this needs to be updated, above answers are now only partially correct:

with the current version of bash, modifying a script on-disk while it is running will cause bash to "try" to load the changes into memory and take these on in the running script. if your changes come after the currently executing line, the new lines will be loaded and executed. but, this is a guess by bash and it may get it right or wrong.

the better way to do this is the following sequence of actions: 1) load the script into memory 2) delete the script from disk 3) write a new script to disk by deleting the disk version first, the memory version loses its links to it so that when you supply a new version in step 3, no attempt by bash will be made to load the new contents into the memory version.

2
  • This explanation is misleading. "load changes into memory" implies that bash had the original in memory. The point is that baah does not change what it already has in memory, but since it doesn't read the entire script before starting to run it, changes to the part it has yet to read will affect it. Mar 21 at 1:41
  • It's also not a matter of "which version of Bash", but rather a matter of "which editor" and "what exactly is in the script" Mar 21 at 1:54
6

I'll add something that I think has not been said in the other answers. Much depends on just how you edit the file. Doing echo "stuff" >file from the shell (another instance) will indeed overwrite the file, I think. But if you edit the file with for instance emacs and then save, this will not happen. Instead here the editor renames the old file to some backup name (maybe actually removing the previous backup), and then write its modified buffer contents as a new file with the (now libreated) old name. Since the shell (or other interpreter) reading the script will almost certainly open the file only once, it is thereafter independent of the whereabouts of the file name, it just continues to read the physical disk file (identified by inode number) that was associated to the file name at the time of opening. So even if it reads the script in blocks (which would be the easiest solution if using buffered text I/O), it would continue to read the lines from the old instance of the file, which is likely to not change by your editing.

2
  • 1
    +1 I am using Sublime Text as my editor. Do you know if it too renames the file, like emacs?
    – becko
    Jun 16, 2014 at 17:03
  • 2
    I think most editors would use a renaming scheme (even if they should not keep backup versions) to avoid the risk that if a crash happened during the write process, no intact version of the text would remain at all. You can check with "ls -i" (which shows inode numbers) what the behaviour of your editor is. Jun 17, 2014 at 3:48
1

@jobin's answer is generally correct, but I'll add some other answers that may be to the point depending what you want to do.

If you want to change the script, and want to know that it's safe, then you want to write to a new file, not the existing one, The new file can be located where the old one was though. Write your new version to a new file, and then use mv to move it into place over the top of the old one. The file that has been replaced still exists, it's just not linked from the directory. Your running script can continue using it, and when that script closes its file handle the system knows that it can safely clean up the file (whether immediately or at a later time).

If you want to behave the behaviour of the script on the fly, you have a more difficult problem. I expect you'd need to build it into the code of the script. Bash scripts can handle signals (eg can catch something like kill -USR1 [pid]), and a script could then respond by reloading some code. So maybe you can get functionality close to what you want, but without knowing what you're after, I'm not seeing a good reason to do this, and I suspect if you want to do something this complex you probably want a more sophisticated programming language to do it in.

If you want to hack the behaviour of a running script that is not written with this in mind, then you're out of luck. I'd hesitate to call any programming task impossible, but if you had the resources and skills for this sort of task, you presumably wouldn't be asking here.

0

The shell is not like other scripting languages.

The shell reads and executes commands one by one, so the simple answer is "yes, editing a running script can affect it", but it's important to understand the details.

If you are careful, you can add lines to the end of a running script, and they will be run after the other commands already in the script.

echo "echo 'This extra command will also run.'" >> yourscript.sh

Some editors may write a new file (inode) with the same name as the old one; any changes made that way won't affect what the shell reads (which is why those editors do that). Thus confounds some attempts at testing this.

But as long as you're still dealing with the same inode, the running shell will be affected if the script is altered beyond the point it has read up to - unless of course it invokes exit before then.

Reading is typically done 4KiB blocks, so that small scripts may appear to run unaffected, but when it's close to the end of file, the shell (like all text processing programs) will read whatever it can get. This "short read" does not by itself signal end-of-file, and the shell will continue to read until it reads no bytes at all. Thus, if the file gets longer while the shell is reading it, the shell will read the new data.

It's important to note at this point that the shell won't attempt to read more data until it needs to, either to finish parsing a compound command, or because it's simply run all the previous commands. That delay is where you have a chance to alter the file containing the script.

So any change that makes the file longer will almost always have some effect.

Editing a file and inserting N bytes in the middle will reposition the last N bytes of the file to just beyond where the end-of-file used to be. Those bytes will be read as "new" by the shell, even if it has just read them at their previous position.

And to complicate things further, because the block and line boundaries probably won't coincide, the shell may read starting part way through a line, giving rise to the "gibberish effect". This can happen happen if you add or delete lines that are before where the shell has read up to.

3
  • This answer is a word-for-word duplicate of this post 🤔
    – matigo
    Mar 22 at 7:58
  • @matigo It's flattering that they copied my answer, but I'm not impressed that they failed to credit me as the source. (Look carefully at the edit history on this answer and you'll see that I worked on it over an extended period.) Mar 23 at 17:19
  • There is credit of sorts: a "see answer" link at the bottom of that page that points to this whole page. Mar 23 at 17:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.