我可以在运行时修改 bash 脚本 (.sh) 文件吗?

bec*_*cko 41 filesystem scripts

假设我有一个脚本script.sh,它需要一些时间来执行。我执行它,./script.sh。当它在终端窗口中运行时,我修改了文件script.sh. 这会对已经运行的进程产生任何影响吗?

修改后,我执行修改后的文件,所以我现在有两个正在运行的进程。这个可以吗?

job*_*bin 47

当您对脚本进行更改时,您会在磁盘(硬盘 - 永久存储)上进行更改;当您执行脚本时,脚本会加载到您的内存(RAM)中。

因此,您对脚本所做的更改不会影响正在运行的脚本,它会运行您在进行这些更改之前执行的版本。

但是,当您在不终止先前运行的实例的情况下再次执行更改的脚本时,将有两个脚本实例 - 一个有更改,一个是旧的。

请注意,脚本使用和修改的资源会发生冲突。例如,如果您正在使用脚本修改文件,则稍后运行的脚本将无法打开该文件进行写入并且无法正确执行。

更新: 感谢注册用户为我指出 Unix.stackexchange.com 上更好的答案。

根据脚本的大小和所讨论的编译器/解释器,脚本会部分/完全加载。因此,如果脚本没有完全加载,一旦脚本的一部分加载到内存中,您对脚本所做的更改将反映在正在运行的实例上。

因此,不建议更改当前正在运行的磁盘上的脚本以获得不可预测的输出:首先停止正在运行的实例,然后修改您的脚本,然后重新执行该脚本。

  • 不是完美的答案,请阅读 http://unix.stackexchange.com/q/121013/55673 (14认同)
  • 当我使用 bash v3.2.48 尝试此操作时(请参阅[此处](http://stackoverflow.com/questions/21096478/overwrite-executing-bash-script-files#21100710)),它没有缓冲超过该行(当我在执行时修改脚本时严重失败)。我刚刚用 bash v4.3.0 重新测试,它缓冲了整个(短)脚本。所以...我不会指望任何特定的行为。 (2认同)

小智 7

这需要更新,以上答案现在只是部分正确:

使用当前版本的 bash,在运行时修改磁盘上的脚本将导致 bash“尝试”将更改加载到内存中并在运行脚本中执行这些更改。如果您的更改发生在当前执行的行之后,则将加载并执行新行。但是,这是 bash 的猜测,它可能正确或错误。

执行此操作的更好方法是以下操作序列:1) 将脚本加载到内存中 2) 从磁盘中删除脚本 3) 通过首先删除磁盘版本将新脚本写入磁盘,内存版本将失去与它的链接这样当您在步骤 3 中提供新版本时,bash 不会尝试将新内容加载到内存版本中。


Mar*_*wen 5

我会补充一些我认为在其他答案中没有说的内容。很大程度上取决于您如何编辑文件。这样做echo "stuff" >file从壳(另一个实例)确实将覆盖该文件,我想。但是,如果您使用例如编辑文件emacs然后保存,则不会发生这种情况。取而代之的是,编辑器将旧文件重命名为某个备份名称(可能实际上删除了以前的备份),然后将其修改后的缓冲区内容写入为具有(现在已释放的)旧名称文件。由于读取脚本的外壳程序(或其他解释器)几乎肯定只会打开文件一次,因此此后与文件的下落无关,它只是继续读取打开时与文件名关联的物理磁盘文件(由 inode 编号标识)。因此,即使它以块为单位读取脚本(如果使用缓冲文本 I/O,这将是最简单的解决方案),它也会继续从文件的旧实例中读取行,这可能不会因您的编辑而改变。

  • 我认为大多数编辑器会使用重命名方案(即使他们不应该保留备份版本)来避免风险,如果在写入过程中发生崩溃,则根本不会保留文本的完整版本。您可以使用“ls -i”(显示 inode 编号)检查编辑器的行为。 (2认同)