shell脚本是否可以指示其行最初是否已加载到内存中?

时间:2010-02-25 19:32:24

标签: bash shell scripting

更新:这是How to make shell scripts robust to source being changed as they run

的转贴

这是一件困扰我的小事:

  1. 我为一个快速而肮脏的工作编写了一个shell脚本(bash)
  2. 我运行脚本,它运行了很长一段时间
  3. 当它正在运行时,我会在脚本中编辑几行,为不同的作业配置
  4. 但是第一个进程仍在读取相同的脚本文件,并且搞砸了。
  5. 显然,脚本是通过从文件中加载每行所需的来解释的。有没有什么方法可以让脚本向shell指示整个脚本文件应该一次性读入内存?例如,Perl脚本似乎这样做:编辑代码文件不会影响当前正在解释它的进程(因为它最初被解析/编译?)。

    我知道有很多方法可以解决这个问题。例如,我可以尝试类似:

    cat script.sh | sh
    

    sh -c "`cat script.sh`"
    

    ...如果脚本文件很大并且流缓冲区和命令行参数的大小有限,那么这些可能无法正常工作。我还可以编写一个辅助包装器,将脚本文件复制到一个锁定的临时文件然后执行它,但这看起来不太便携。

    所以我希望最简单的解决方案只涉及对脚本的修改,而不是调用它的方式。我可以在脚本开头添加一行或两行吗?我不知道这样的解决方案是否存在,但我猜它可能会使用$ 0变量......

6 个答案:

答案 0 :(得分:8)

我发现的最佳答案是对How to make shell scripts robust to source being changed as they run提供的解决方案的微小变化。感谢camh注意到转贴!

#!/bin/sh
{
    # Your stuff goes here
    exit
}

这可以确保最初解析所有代码;请注意,“退出”对于确保稍后不访问该文件以查看是否还有其他行要解释至关重要。另外,如前一篇文章所述,这并不能保证脚本调用的其他脚本是安全的。

感谢大家的帮助!

答案 1 :(得分:2)

如何编辑它的解决方案。

如果脚本正在运行,则在编辑之前,请执行以下操作:

mv script script-old
cp script-old script
rm script-old

由于shell保持文件打开,只要你不改变open inode的内容,一切都会正常工作。

以上是有效的,因为mv将保留旧的inode,而cp将创建一个新的inode。由于文件的内容在打开时实际上不会被删除,因此您可以立即将其删除,并在shell关闭文件后将其清除。

答案 2 :(得分:2)

使用不修改现有文件的编辑器,而是创建新文件,然后替换旧文件。例如,在Vim中使用:set writebackup backupcopy=no

答案 3 :(得分:1)

根据bash文档而不是

#!/bin/bash
body of script

你试试

#!/bin/bash
script=$(cat <<'SETVAR'
body of script
SETVAR)
eval "$script"

然后我认为你会出差。

答案 4 :(得分:0)

考虑为快速和肮脏的工作创建一个新的爆炸路径。如果您使用以下命令启动脚本: #!/usr/local/fastbash

或者其他什么,那么你可以编写一个使用你提到的方法之一的fastbash包装器。为了便于移植,可以创建一个从fastbash到bash的符号链接,或者在脚本中有一条注释说可以用bash替换fastbash。

答案 5 :(得分:0)

如果您使用Emacs,请尝试M-x customize-variable break-hardlink-on-save。设置此变量将告诉Emacs写入临时文件,然后将temp文件重命名为原始文件,而不是直接编辑原始文件。这应该允许正在运行的实例在保存新版本时保留其未修改的版本。

据推测,其他半智能编辑也会有类似的选择。