在shell脚本运行时编辑它

ack*_*ack 81 linux shell csh

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

我很好奇csh脚本的具体情况,我有批处理运行一堆不同的构建风格并运行一整夜.如果我在操作过程中发生了某些事情,我想进入并添加其他命令,或者注释掉未执行的命令.

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

当然我已经尝试过了,但是在我看到它是否有效之前还需要几个小时,而且我很好奇幕后发生了什么或者没有发生什么.

tei*_*ura 47

[编辑]参见这个答案,第3节了解变通方法.

确实会影响,至少在我的环境中受到打击,但却非常不愉快.请参阅这些代码.第一a.sh:

#!/bin/sh

echo "First echo"
read y

echo "$y"

echo "That's all."
Run Code Online (Sandbox Code Playgroud)

b.sh:

#!/bin/sh

echo "First echo"
read y

echo "Inserted"

echo "$y"

# echo "That's all."
Run Code Online (Sandbox Code Playgroud)

$ cp a.sh run.sh
$ ./run.sh
$ # open another terminal
$ cp b.sh run.sh  # while 'read' is in effect
$ # Then type "hello."
Run Code Online (Sandbox Code Playgroud)

在我的情况下,输出始终是:

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

这是不可预测的,因此是危险的.有关变通方法,请参阅此答案第3节.

[补充]确切的行为取决于一个额外的换行符,也可能取决于你的Unix风格,文件系统等.如果你只是想看到一些影响,只需在b.sh之前和/或之后添加"echo foo/bar" "读"行.

  • 嗯,我没有看到感情.我错过了什么吗? (3认同)

Eri*_*sty 35

试试这个......创建一个名为"bash-is-odd.sh"的文件:

#!/bin/bash
echo "echo yes i do odd things" >> bash-is-odd.sh
Run Code Online (Sandbox Code Playgroud)

这表明bash确实是在"你去的时候"解释剧本.实际上,编辑长时间运行的脚本会产生不可预测的结果,插入随机字符等等.为什么?因为bash从最后一个字节位置读取,所以编辑会移动当前正在读取的字符的位置.

总之,由于这个"特征",Bash非常非常不安全.与bash脚本一起使用时,svn和rsync特别令人不安,因为默认情况下它们会"合并"结果......编辑到位.rsync有一个修复此问题的模式.svn和git没有.

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

#!/bin/bash
source "$1"
Run Code Online (Sandbox Code Playgroud)

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

由@ AF7提出/测试的替代(在线)解决方案:

{
   # your script
} 
exit $?
Run Code Online (Sandbox Code Playgroud)

卷曲支撑可防止编辑,退出可防止附加.当然,如果bash带有一个选项,比如'-w'(整个文件),或者做了这样的事情,我们都会好得多.

  • 一个简单的解决方案,由我的朋友Giulio向我建议(应当到期)是在scritp的开头和}结尾处插入.Bash被迫阅读内存中的所有内容. (10认同)
  • 我不能推荐这个。在此解决方法中,位置参数移动一位。另请记住,您不能将值赋给 $0。这意味着如果您只是将“/bin/bash”更改为“/bin/bashx”,许多脚本都会失败。 (2认同)
  • 请告诉我这样的选项已经实施了! (2认同)
  • @korkman是的,我同意,这就是为什么`bashx`肯定解决了问题,但是像`{...};这样的解决方案 exit $?` 可能会出现在代码(安全)和 exit 命令(不安全)之间编辑文件的竞争。我认为你必须将出口放在花括号中才能确定。 (2认同)

gle*_*man 17

将脚本分解为函数,每次source从单独的文件调用函数时.然后,您可以随时编辑文件,并且您的运行脚本将在下次获取更改时获取更改.

foo() {
  source foo.sh
}
foo
Run Code Online (Sandbox Code Playgroud)


小智 5

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

#!/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"
Run Code Online (Sandbox Code Playgroud)

在 Linux 下,如果您输入得足够快,对正在执行的 .sh 所做的更改似乎是由正在执行的脚本执行的!


for*_*ord -88

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

将此脚本分解为多个文件并单独运行它们可能是明智的做法。这将减少执行失败的时间。(即,将批次拆分为一个构建风格脚本,单独运行每个脚本以查看哪个脚本造成了问题)。

  • 我观察到相反的情况。运行经过编辑的 bash 脚本可能会导致正在运行的脚本崩溃,因为该文件似乎在 bash 脚本读取文件位置下移动。 (80认同)
  • 根据我在多个系统上的经验,执行副本并不独立于磁盘文件,这就是为什么这个问题在 shell 脚本编程中如此令人惊讶和重要。 (12认同)
  • 你不正确。它的缓冲取决于实现和脚本中调用的实际命令,标准输出是否重定向到文件,有很多因素,您的答案并不简单正确。 (10认同)
  • 它绝对_不_独立于光盘上的文件。shell 通常只是以块的形式读取脚本,例如 128 字节或 4096 字节或 16384 字节,并且仅在需要新输入时才读取下一个块。(您可以在运行脚本的 shell 上执行诸如 lsof 之类的操作,并查看它仍然打开了文件。) (7认同)
  • 不会。实际上,如果您编辑脚本,则会导致进程失败。 (6认同)
  • @ford - 这可能是您所观察到的,但我怀疑这是您的编辑器抛出的红鲱鱼 - 它可能会创建一个新文件并将其移动到每次保存时的位置,而不是直接编辑文件。 (2认同)