Edit shell script while it's running

匿名 (未验证) 提交于 2019-12-03 03:06:01

问题:

Can you edit a shell script while it's running and have the changes affect the running script?

I'm curious about the specific case of a csh script I have that batch runs a bunch of different build flavors and runs all night. If something occurs to me mid operation, I'd like to go in and add additional commands, or comment out un-executed ones.

If not possible, is there any shell or batch-mechanism that would allow me to do this?

Of course I've tried it, but it will be hours before I see if it worked or not, and I'm curious about what's happening or not happening behind the scenes.

回答1:

Scripts don't work that way; the executing copy is independent from the source file that you are editing. Next time the script is run, it will be based on the most recently saved version of the source file.

It might be wise to break out this script into multiple files, and run them individually. This will reduce the execution time to failure. (ie, split the batch into one build flavor scripts, running each one individually to see which one is causing the trouble).



回答2:

[edit] See also this answer, section 3 for workarounds.

It does affect, at least bash in my environment, but in very unpleasant way. See these codes. First a.sh:

#!/bin/sh  echo "First echo" read y  echo "$y"  echo "That's all." 

b.sh:

#!/bin/sh  echo "First echo" read y  echo "Inserted"  echo "$y"  # echo "That's all." 

Do

$ cp a.sh run.sh $ ./run.sh $ # open another terminal $ cp b.sh run.sh  # while 'read' is in effect $ # Then type "hello." 

In my case, the output is always:

hello hello That's all. That's all.

This is unpredictable, thus dangerous. See this answer, section 3 for workarounds.

[added] The exact behavior depends on one extra newline, and perhaps also on your Unix flavor, filesystem, etc. If you simply want to see some influences, simply add "echo foo/bar" to b.sh before and/or after the "read" line.



回答3:

Try this... create a file called "bash-is-odd.sh":

#!/bin/bash echo "echo yes i do odd things" >> bash-is-odd.sh 

That demonstrates that bash is, indeed, interpreting the script "as you go". Indeed, editing a long-running script has unpredictable results, inserting random characters etc. Why? Because bash reads from the last byte position, so editing shifts the location of the current character being read.

Bash is, in a word, very, very unsafe because of this "feature". svn and rsync when used with bash scripts are particularly troubling, because by default they "merge" the results... editing in place. rsync has a mode that fixes this. svn and git do not.

I present a solution. Create a file called "/bin/bashx":

#!/bin/bash source "$1" 

Now use #!/bin/bashx on your scripts and always run them with "bashx" instead of bash. This fixes the issue - you can safely rsync your scripts.

Alternative (in-line) solution proposed/tested by @AF7:

{    # your script }  exit $? 

Curly braces protect against edits, and exit protects against appends. Of course we'd all be much better off if bash came with an option, like '-w' (whole file), or something that did this.



回答4:

Break your script into functions, and each time a function is called you source it from a separate file. Then you could edit the files at any time and your running script will pick up the changes next time it gets sourced.

foo() {   source foo.sh } foo 


回答5:

I don't have csh installed, but

#!/bin/sh echo Waiting... sleep 60 echo Change didn't happen 

Run that, quickly edit the last line to read

echo Change happened 

Output is

Waiting... /home/dave/tmp/change.sh: 4: Syntax error: Unterminated quoted string 

Hrmph.

I guess edits to the shell scripts don't take effect until they're rerun.



回答6:

If this is all in a single script, then no it will not work. However, if you set it up as a driver script calling sub-scripts, then you might be able to change a sub-script before it's called, or before it's called again if you're looping, and in that case I believe those changes would be reflected in the execution.



回答7:

I'm hearing no... but what about with some indirection:

BatchRunner.sh

Command1.sh Command2.sh 

Command1.sh

runSomething 

Command2.sh

runSomethingElse 

Then you should be able to edit the contents of each command file before BatchRunner gets to it right?

OR

A cleaner version would have BatchRunner look to a single file where it would consecutively run one line at a time. Then you should be able to edit this second file while the first is running right?



回答8:

usually, it uncommon to edit your script while its running. All you have to do is to put in control check for your operations. Use if/else statements to check for conditions. If something fail, then do this, else do that. That's the way to go.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!