Vagrant 机器无法 运行 正确使用 - 如何在 Vagrant shell 脚本中转义反斜杠
Vagrant machine wont run SED correctly - How to escape backslashes in Vagrant shell scripts
我有一个问题,我无法解决 vagrant provisioning 问题。我有一个包含反斜杠的文件,我需要将其删除,但 Vagrant (Ruby?) 不会这样做,我已经尝试了 2 天了。
Vagrant.configure("2") do |config|
%w{test2 }.each_with_index do |name, i|
config.vm.define name do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "test#{i + 2}"
vb.memory = 512
vb.cpus = 1
end
node.vm.box = "ubuntu/focal64"
node.disksize.size = "1GB"
node.vm.hostname = name
node.vm.network :private_network, ip: "10.0.5.#{i + 12}"
node.vm.provision :shell, privileged: false, inline: <<-SHELL
cat /vagrant/control_join_file.sh | tr -d '\n' > /vagrant/control_join_file#{i + 12}.sh
sed -i -E "s@\@ @" /vagrant/control_join_file#{i + 12}.sh
chmod +x /vagrant/control_join_file#{i + 12}.sh
sudo /vagrant/control_join_file#{i + 12}.sh
SHELL
end
end
end
下面这行是罪魁祸首,如果我把它注释掉就会发生。
sed -i -E "s@\@ @" /vagrant/control_join_file#{i + 12}.sh
我将分隔符更改为 @ 符号并尝试了数百种方法。我真的希望有人能指出这里的错误。
此外,如果我 运行 它喜欢这样它就可以工作。我可以查看创建的文件,果然 4 已更改为百分号。问题似乎与反斜杠有关。
sed -i -E "s@4@%@" /vagrant/control_join_file#{i + 12}.sh
事实证明这个问题比你想象的要复杂。问题是你在这里进行了三个字符串插值阶段。每个阶段都需要正确转义字符串和反斜杠,以便最终 sed
命令正确:
- Ruby 对 heredoc
<<-SHELL
字符串进行字符串插值。
- 执行脚本的shell自己插值
- Sed 对您提供的正则表达式进行自己的插值。
让我们从第 3 阶段开始倒推,以便我们在开始其他阶段之前知道最终要求是什么。
第 3 阶段 - Sed
我们知道 sed 要求在其正则表达式中对反斜杠进行转义。所以sed命令需要下面的字符串s/\/ /
.
然后问题就变成了:我们如何将那个字符串准确地提供给 sed?
第 2 阶段 - Shell
我们知道我们必须向 sed 提供两个反斜杠。让我们 运行 在 shell 中进行一些测试,看看它如何转义反斜杠:
$ echo "\"
\
啊哈。结果是 shell (bash) 在双引号内插入了反斜杠。单引号呢?
$ echo '\'
\
嗯,这很有用。这意味着我们可以使用单引号来防止 Bash.
中的反斜杠插值
我们来测试一下:
$ echo '\' | sed -E 's/\/X/'
X\
这似乎有效。注意,如果要替换所有反斜杠,需要使用g
修饰符:
$ echo '\' | sed -E 's/\/X/g'
XX
好的。看来我们已经收集了进入阶段 1 的所有拼图。
阶段 1 - Ruby
在 Ruby 中,heredoc <<-SHELL
运算符进行自己的字符串插值。因此需要转义反斜杠。
让我们在irb
中测试一下:
> puts <<-SHELL
sed -E 's/\\/ /' ...
SHELL
sed -E 's/\/ /' ...
看起来不错!
到目前为止我们学到了什么:
- Ruby heredoc
<<-SHELL
要求转义反斜杠。
- shell(Bash 或 sh),需要反斜杠进行转义,除非使用单引号.
- Sed 需要两个反斜杠。
现在我们可以 assemble 我们的脚本正确了:
node.vm.provision :shell, privileged: false, inline: <<-SHELL
...
sed -i -E 's/\\/ /' /vagrant/control_join_file#{i + 12}.sh
...
SHELL
我有一个问题,我无法解决 vagrant provisioning 问题。我有一个包含反斜杠的文件,我需要将其删除,但 Vagrant (Ruby?) 不会这样做,我已经尝试了 2 天了。
Vagrant.configure("2") do |config|
%w{test2 }.each_with_index do |name, i|
config.vm.define name do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "test#{i + 2}"
vb.memory = 512
vb.cpus = 1
end
node.vm.box = "ubuntu/focal64"
node.disksize.size = "1GB"
node.vm.hostname = name
node.vm.network :private_network, ip: "10.0.5.#{i + 12}"
node.vm.provision :shell, privileged: false, inline: <<-SHELL
cat /vagrant/control_join_file.sh | tr -d '\n' > /vagrant/control_join_file#{i + 12}.sh
sed -i -E "s@\@ @" /vagrant/control_join_file#{i + 12}.sh
chmod +x /vagrant/control_join_file#{i + 12}.sh
sudo /vagrant/control_join_file#{i + 12}.sh
SHELL
end
end
end
下面这行是罪魁祸首,如果我把它注释掉就会发生。
sed -i -E "s@\@ @" /vagrant/control_join_file#{i + 12}.sh
我将分隔符更改为 @ 符号并尝试了数百种方法。我真的希望有人能指出这里的错误。
此外,如果我 运行 它喜欢这样它就可以工作。我可以查看创建的文件,果然 4 已更改为百分号。问题似乎与反斜杠有关。
sed -i -E "s@4@%@" /vagrant/control_join_file#{i + 12}.sh
事实证明这个问题比你想象的要复杂。问题是你在这里进行了三个字符串插值阶段。每个阶段都需要正确转义字符串和反斜杠,以便最终 sed
命令正确:
- Ruby 对 heredoc
<<-SHELL
字符串进行字符串插值。 - 执行脚本的shell自己插值
- Sed 对您提供的正则表达式进行自己的插值。
让我们从第 3 阶段开始倒推,以便我们在开始其他阶段之前知道最终要求是什么。
第 3 阶段 - Sed
我们知道 sed 要求在其正则表达式中对反斜杠进行转义。所以sed命令需要下面的字符串s/\/ /
.
然后问题就变成了:我们如何将那个字符串准确地提供给 sed?
第 2 阶段 - Shell
我们知道我们必须向 sed 提供两个反斜杠。让我们 运行 在 shell 中进行一些测试,看看它如何转义反斜杠:
$ echo "\"
\
啊哈。结果是 shell (bash) 在双引号内插入了反斜杠。单引号呢?
$ echo '\'
\
嗯,这很有用。这意味着我们可以使用单引号来防止 Bash.
中的反斜杠插值我们来测试一下:
$ echo '\' | sed -E 's/\/X/'
X\
这似乎有效。注意,如果要替换所有反斜杠,需要使用g
修饰符:
$ echo '\' | sed -E 's/\/X/g'
XX
好的。看来我们已经收集了进入阶段 1 的所有拼图。
阶段 1 - Ruby
在 Ruby 中,heredoc <<-SHELL
运算符进行自己的字符串插值。因此需要转义反斜杠。
让我们在irb
中测试一下:
> puts <<-SHELL
sed -E 's/\\/ /' ...
SHELL
sed -E 's/\/ /' ...
看起来不错!
到目前为止我们学到了什么:
- Ruby heredoc
<<-SHELL
要求转义反斜杠。 - shell(Bash 或 sh),需要反斜杠进行转义,除非使用单引号.
- Sed 需要两个反斜杠。
现在我们可以 assemble 我们的脚本正确了:
node.vm.provision :shell, privileged: false, inline: <<-SHELL
...
sed -i -E 's/\\/ /' /vagrant/control_join_file#{i + 12}.sh
...
SHELL