在运行时编辑 shell 脚本
- 2024-10-22 08:28:00
- admin 原创
- 322
问题描述:
您可以在 shell 脚本运行时对其进行编辑,并且这些更改是否会影响正在运行的脚本?
我对我手上的一个 csh 脚本的具体情况感到好奇,该脚本批量运行大量不同的构建风格,并运行一整晚。如果在操作过程中出现问题,我会进入并添加其他命令,或注释掉未执行的命令。
如果不可能的话,是否有任何 shell 或批处理机制可以让我做到这一点?
我当然尝试过,但还需要几个小时才能知道它是否有效,我很好奇幕后发生了什么或没有发生什么。
解决方案 1:
它确实有影响,至少对我环境中的 bash 有影响,但影响非常大。请参阅这些代码。首先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."
做
$ cp a.sh run.sh
$ ./run.sh
$ # open another terminal
$ cp b.sh run.sh # while 'read' is in effect
$ # Then type "hello."
就我而言,输出始终是:
你好
你好
就这样。
就这样。
(当然,自动化更好,但上面的例子也是可读的。)
[编辑] 这是不可预测的,因此很危险。最好的解决方法是 ,如此处所述 ,将所有内容放在括号中,并在右括号之前输入“exit”。仔细阅读链接的答案以避免陷阱。
[添加] 确切的行为取决于一个额外的换行符,也可能取决于您的 Unix 风格、文件系统等。如果您只是想看到一些影响,只需在“读取”行之前和/或之后将“echo foo/bar”添加到 b.sh 即可。
解决方案 2:
尝试一下...创建一个名为的文件bash-is-odd.sh
:
#!/bin/bash
echo "echo yes i do odd things" >> bash-is-odd.sh
这表明 bash 确实在“随你执行”地解释脚本。事实上,编辑长时间运行的脚本会产生不可预测的结果,插入随机字符等。为什么?因为 bash 从最后一个字节位置读取,所以编辑会移动当前正在读取的字符的位置。
简而言之,由于这个“特性”,Bash 非常非常不安全。svn 和rsync
bash 脚本一起使用时尤其麻烦,因为默认情况下它们会“合并”结果......就地编辑。rsync
有一种模式可以解决这个问题。svn 和 git 没有。
我提出一个解决方案。创建一个名为的文件/bin/bashx
:
#!/bin/bash
source "$1"
现在,#!/bin/bashx
在脚本上使用 并始终使用bashx
而不是 来运行它们bash
。这解决了该问题 - 您可以安全地运行rsync
脚本。
@AF7 提出/测试的替代(在线)解决方案:
{
# your script
exit $?
}
花括号可防止编辑,而 exit 可防止追加。当然,如果 bash 带有选项(如-w
(whole file))或者其他可以执行此操作的程序,我们都会感觉好很多。
解决方案 3:
将脚本拆分为函数,每次调用函数时,都会source
从单独的文件中调用它。然后,您可以随时编辑这些文件,并且正在运行的脚本将在下次获取源代码时获取更改。
foo() {
source foo.sh
}
foo
解决方案 4:
好问题!希望这个简单的脚本能帮到你
#!/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 所做的更改似乎会由正在执行的脚本来实施!
解决方案 5:
一个有趣的旁注 - 如果您正在运行 Python 脚本,它不会改变。(对于任何了解 shell 如何运行 Python 脚本的人来说,这可能都是显而易见的,但我认为对于那些寻找此功能的人来说,这可能是一个有用的提醒。)
我创建了:
#!/usr/bin/env python3
import time
print('Starts')
time.sleep(10)
print('Finishes unchanged')
然后在另一个 shell 中,当它处于休眠状态时,编辑最后一行。完成后,它会显示未更改的行,大概是因为它正在运行.pyc
?Ubuntu 和 macOS 上也会发生同样的情况。
解决方案 6:
我没有安装 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
哼。
我猜测对 shell 脚本的编辑只有重新运行后才会生效。
解决方案 7:
如果所有这些都包含在一个脚本中,那么它不会起作用。但是,如果您将其设置为调用子脚本的驱动程序脚本,那么您可能能够在调用子脚本之前更改它,或者在循环中再次调用它之前更改它,在这种情况下,我相信这些更改将反映在执行中。
解决方案 8:
我听说没有...但是如果用一些间接的方式呢:
批处理运行器
Command1.sh
Command2.sh
命令1.sh
runSomething
命令2.sh
runSomethingElse
那么您应该能够在 BatchRunner 执行操作之前编辑每个命令文件的内容,对吗?
或者
更简洁的版本会让 BatchRunner 查找单个文件,然后每次连续运行一行。那么您应该能够在第一个文件运行时编辑第二个文件,对吗?
解决方案 9:
请使用 Zsh 来编写脚本。
据我所知,Zsh 不会表现出这种令人沮丧的行为。
解决方案 10:
通常,在脚本运行时编辑脚本并不常见。您所要做的就是对操作进行控制检查。使用 if/else 语句检查条件。如果失败,则执行此操作,否则执行该操作。这就是方法。
解决方案 11:
脚本不是这样工作的;执行副本独立于您正在编辑的源文件。下次运行脚本时,它将基于最近保存的源文件版本。
将此脚本拆分成多个文件并单独运行它们可能是明智之举。这将减少执行失败的时间。(即,将批处理拆分为一个构建风格脚本,单独运行每个脚本以查看哪个脚本导致了问题)。