在运行时编辑 shell 脚本

您可以在运行 shell 脚本时编辑它并让更改影响正在运行的脚本吗?

我很好奇我有一个 csh 脚本的具体情况,这个脚本批处理运行许多不同的构建风格,并且整晚都在运行。如果在操作过程中发生了什么事情,我想进入系统并添加额外的命令,或者注释掉未执行的命令。

如果不可能,是否有任何 shell 或批处理机制允许我这样做?

我当然试过了,但是要过几个小时我才能知道它是否有效,我很好奇幕后到底发生了什么或者没有发生什么。

55823 次浏览

脚本不是这样工作的; 正在执行的副本独立于您正在编辑的源文件。下次运行该脚本时,它将基于源文件的最新保存版本。

将此脚本分成多个文件并单独运行它们可能是明智的。这将减少失败的执行时间。(例如,将批处理分割成一个构建风味脚本,分别运行每个脚本以查看哪个脚本造成了麻烦)。

我没有安装 csh,但是

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

运行它,快速编辑要读取的最后一行

echo Change happened

输出是

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

Hrmph.

我猜对 shell 脚本的编辑在重新运行之前不会生效。

通常,在脚本运行时编辑脚本是不常见的。你所要做的就是对你的操作进行控制检查。使用 if/else 语句检查条件。如果某些事情失败了,那么就做这个,否则就做那个。就是这样。

我听到的是否定的... 但是间接的怎么样:

BatchRunner.sh

Command1.sh
Command2.sh

命令1.sh

runSomething

命令2.sh

runSomethingElse

那么您应该能够在 BatchRunner 获得正确的内容之前编辑每个命令文件的内容?

或者

更干净的版本会让 BatchRunner 查看一个文件,在这个文件中它将连续地一次运行一行。那么当第一个文件正常运行时,您应该能够编辑第二个文件?

如果这一切都在一个单一的脚本,那么不,它不会工作。然而,如果你把它设置成一个调用子脚本的驱动程序脚本,那么你就可以在调用它之前更改一个子脚本,或者在循环中再次调用它之前更改一个子脚本,在这种情况下,我相信这些更改会反映在执行中。

将脚本分解成函数,每次调用一个函数时,从一个单独的文件调用它。然后您可以在任何时候编辑这些文件,并且您的运行脚本将在下次获得源代码时获取这些更改。

foo() {
source foo.sh
}
foo

它受到 does的影响,至少在我的环境中受到 bash 的影响,但是在 非常不愉快的方式中受到影响:

#!/bin/sh


echo "First echo"
read y


echo "$y"


echo "That's all."

返回文章页面

#!/bin/sh


echo "First echo"
read y


echo "Inserted"


echo "$y"


# echo "That's all."

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

在我的例子中,输出总是:

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

(Of course it's far better to automate it, but the above example is readable.)

[编辑]这是不可预测的,因此是危险的。 最好的解决办法是as described here 把所有东西放在一个花括号里,在闭合花括号之前,写上“ exit”仔细阅读链接的答案避免陷阱。

确切的行为取决于一个额外的换行符,也许还取决于您的 Unix 风格、文件系统等。如果您只是想看到一些影响,只需在“ read”行之前和/或之后向 b.sh 添加“ echo foo/bar”即可。

试试这个... 创建一个名为 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 非常非常不安全。Svn 和 rsync在与 bash 脚本一起使用时尤其麻烦,因为默认情况下它们会“合并”结果... ... 就地编辑。rsync的模式可以解决这个问题。Svn 和 git 没有。

我提出了一个解决方案。创建一个名为 /bin/bashx的文件:

#!/bin/bash
source "$1"

现在在脚本上使用 #!/bin/bashx,并始终使用 bashx而不是 bash运行它们。这修复了问题-您可以安全地 rsync您的脚本。

由@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.

问得好! 希望这个简单的脚本有所帮助

#!/bin/sh
echo "Waiting..."
echo "echo \"Success! Edits to a .sh while it executes do affect the executing script! I added this line to myself during execution\"  " >> ${0}
sleep 5
echo "When I was run, this was the last line"

在 linux 下,对执行文件所做的更改似乎确实存在。Sh 是由执行脚本制定的,如果你能够输入足够快!

一个有趣的附注——如果您正在运行 Python 脚本,它不会改变。(对于理解 shell 如何运行 Python 脚本的人来说,这可能是显而易见的,但是对于寻找这个功能的人来说,这可能是一个有用的提醒。)

我创造了:

#!/usr/bin/env python3
import time
print('Starts')
time.sleep(10)
print('Finishes unchanged')

然后在另一个 shell 中,在这个 shell 处于睡眠状态时,编辑最后一行。当这完成时,它显示未更改的行,大概是因为它正在运行一个 .pyc?Ubuntu 和 macOS 也是如此。

在编写脚本时使用 Zsh。

Zsh 没有表现出这种令人沮丧的行为。