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?
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.
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.
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 instanceemacs
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.@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.
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.
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.