【问题标题】:Is it possible in a bash script to change its content while it's running?bash 脚本是否可以在运行时更改其内容?
【发布时间】:2017-08-04 03:21:24
【问题描述】:

短版: bash 脚本是否可以在运行时更改其内容?

加长版: 我有一个 bash 脚本,我想在它运行时将其 EOL 从 CRLF'\r\n' 更改为 LF'\n'。目前,到目前为止我能做的就是把这行放在脚本的顶部:

sed -i -e "s/\r$//g; s/^sed -i -e/#sed -i -e/g" $(basename $0); echo "Rerun again.." ; exit 0;

但这肯定是不切实际的。

我在想,当脚本在第一行运行时,它会创建一个子 shell 并将当前 shell 的内容放在那里,进行一些更改并将其放回上层 shell。 这有可能吗?

做同样的想法,但要在新的临时脚本中创建当前脚本的副本:

cat $0 > temp.sh

然后主脚本将执行 temp.sh,脚本完成后,它将 temp.sh 的副本捕获回主脚本并删除 temp.sh。 我认为这在理论上可行,但我确信有一些更简单的方法。

注意:这与 EOL 无关,我有一些我自己的脚本 需要应用相同的功能。

使用示例: 该项目涉及在windows和linux上运行脚本,如果任何用户在windows上通过编辑器打开脚本,它将EOL保存为windows格式,即'\n\r',这将在windows上出现此错误:

./script.sh: line 5: syntax error near unexpected token `$'{\r''
'/script.sh: line 5: `foo(){

这就是我在脚本开头使用 sed 的原因。

【问题讨论】:

  • 我不明白为什么脚本应该修改自己(预期的结果是什么),但无论如何,永远不要这样做,因为结果是未定义的。 Bash 不一定(而且 AFIK 通常确实不会)首先将整个脚本读入内存,但可以稍后加载其中的一部分,只记住文件中要继续的位置。
  • 我已将此案例添加为工单的更新。如果用户在 Windows 上更改了 EOL,则会出现错误。

标签: linux windows bash shell


【解决方案1】:

不要更改当前正在运行的脚本。

一旦我有一个非常慢的脚本并且在执行过程中我开始调整它以准备下一次执行。它开始表现得很奇怪。在我看来 bash 只读取脚本的开头并稍后读取其他部分。所以一开始我的脚本很短时这不是问题,但随着我的脚本变长它开始引起问题。

【讨论】:

  • 确实如此,因为 bash 总是毫无问题地继续第一行,这就是为什么我在上面添加了我提到的 sn-p。但我一直在寻找比我的解决方案更实用的东西。
【解决方案2】:

您可以扩展您当前的尝试:

[[ -z "$CANARY" ]] && { sed -i -e 's/\r$//g' "${BASH_SOURCE[0]}"; CANARY=1 exec "${BASH_SOURCE[0]}"; }

基本上,您测试一些变量,进行修改,然后在设置变量时使用修改后的源重新执行。

你也可以source它而不是execing,而不是修改实际的脚本文件:

[[ -z "$CANARY" ]] && { CANARY=1 source <(sed 's/\r$//g' "${BASH_SOURCE[0]}"); exit }

【讨论】:

  • 我会试试这个,但我试图找到一种比退出后评论该行更简洁的方法。因为有些用户居然把评论的版本推送到repo了,麻烦就出现了。
  • @Sam 为什么要评论什么?退出后,脚本永远不会到达后面的行,除非它已经被处理过
  • 问题是在 bash 成功完成第一行并且已经执行了 'sed' 之后,脚本的新修改版本不会产生任何影响,它会引发错误。然后用户应该再次运行它,它会运行正常。所以用户应该运行脚本两次。我一直在寻找其他更简洁的方法来打开脚本,它会自我更新,保存上下文,然后执行正文。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 2013-01-31
  • 2017-10-12
  • 1970-01-01
  • 2015-09-23
  • 2017-04-18
相关资源
最近更新 更多