У меня проблема, я не могу обойти 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
была правильной:
<<-SHELL
.Давайте работать в обратном порядке, начиная с этапа 3, чтобы мы знали, каковы конечные требования, прежде чем мы начнем с других этапов.
Этап 3 - Сед
Мы знаем, что sed требует экранирования обратной косой черты в регулярном выражении. Итак, команде sed нужна следующая строка s/\/ /
.
Тогда возникает вопрос: как передать именно эту строку в sed?
Этап 2 - Оболочка
Мы ЗНАЕМ, что нам нужно передать две обратные косые черты для sed. Давайте запустим некоторый тест в оболочке и посмотрим, как он избегает обратной косой черты:
$ echo "\\"
\
Ага. Оказывается, оболочка (bash) интерполирует обратную косую черту внутри двойных кавычек. Как насчет одинарных кавычек?
$ echo '\\'
\\
Ну это полезно. Это означает, что мы можем использовать одинарные кавычки, чтобы предотвратить интерполяцию обратной косой черты в Bash.
Давайте проверим это:
$ echo '\\' | sed -E 's/\/X/'
X\
Кажется, это работает. Обратите внимание, что если вы хотите заменить все обратные косые черты, вам нужно использовать модификатор g
:
$ echo '\\' | sed -E 's/\/X/g'
XX
В порядке. Кажется, мы собрали все кусочки головоломки для перехода к этапу 1.
Этап 1 - Рубин
В Ruby оператор heredoc <<-SHELL
выполняет собственную интерполяцию строк. Поэтому обратную косую черту необходимо экранировать.
Давайте проверим это в irb
:
> puts <<-SHELL
sed -E 's/\\\/ /' ...
SHELL
sed -E 's/\/ /' ...
Выглядит неплохо!
Что мы узнали на данный момент:
<<-SHELL
требует экранирования обратной косой черты.Теперь мы можем правильно собрать наш скрипт:
node.vm.provision :shell, privileged: false, inline: <<-SHELL
...
sed -i -E 's/\\\/ /' /vagrant/control_join_file#{i + 12}.sh
...
SHELL
большое спасибо за подробное объяснение. Должен сказать, что каким-то образом я уже пробовал это (пробовал до 8 обратных слэшей), но это не сработало, поэтому я продолжил. Я, должно быть, только что потерял одну часть головоломки. но благодаря вам теперь у меня все работает как надо! Я знаю, что это отняло у вас время, но я хочу, чтобы вы знали, что я очень ценю ваш подробный ответ.
Вы пробовали обычную вещь, удваивая обратную косую черту?
sed -i -E "s@\\\\@ @" /vagrant/control_join_file#{i + 12}.sh