Назад | Перейти на главную страницу

Как избежать «/» в команде sed в сценарии Puppet?

В конфигурационном файле пытаюсь заменить PREFIX=/jenkins с, скажем, PREFIX=/foobar.

В командной строке (bash) это отлично работает:

sed -i.bak s/PREFIX=\\/jenkins/PREFIX=\\/foobar/g /etc/default/jenkins

Однако в сценарии Puppet (файл .pp):

exec { 'Change-prefix':
  command => "sed -i.bak s/PREFIX=\\/jenkins/PREFIX=\\/foobar/g /etc/default/jenkins",
  path    => ["/bin"],
}

производит:

err: /Stage[main]//Exec[Change-prefix]/returns: change from notrun to 0 failed:
sed -i.bak s/PREFIX=\/jenkins/PREFIX=\/foobar/g /etc/default/jenkins 
returned 1 instead of one of [0] 

Как правильно выйти из команды sed? Или дело в другом?

Я также пробовал с \\\/, но это дает: warning: Unrecognised escape sequence '\/'

Во многих версиях sed вы можете использовать другой символ в качестве разделителя, чтобы избежать необходимости экранировать / например, довольно часто использовать | или #

sed -i.bak 's#PREFIX=/jenkins#PREFIX=/foobar#g' /etc/default/jenkins

В тех случаях, когда ваше выражение sed содержит '/', вы можете рассмотреть возможность использования другого разделителя. В этом примере я выбрал символ трубы.

sed -i.bak 's|PREFIX=/jenkins|PREFIX=/foobar|g' /etc/default/jenkins

На мой взгляд, использование этого синтаксиса в манифесте Puppet было бы намного чище и удобочитаемее.


На странице информации sed:

\%REGEXP%' (The% 'может быть заменен любым другим одиночным символом.)

 This also matches the regular expression REGEXP, but allows one to
 use a different delimiter than `/'.  This is particularly useful
 if the REGEXP itself contains a lot of slashes, since it avoids
 the tedious escaping of every `/'.  If REGEXP itself includes any
 delimiter characters, each must be escaped by a backslash (`\').

Эй, стой ... подождите! Сед в марионеточном манифесте немного сумасшедший. Вы должны использовать ресурс file_line из библиотеки puppetlabs stdlib.

(вы должны установить весь модуль, но вот пользовательский тип ресурса) https://github.com/puppetlabs/puppetlabs-stdlib/blob/master/lib/puppet/type/file_line.rb

Пример:

  file_line { 'sudo_rule':
    path => '/etc/sudoers',
    line => '%sudo ALL=(ALL) ALL',
  }

Оказывается \\\\/ работает.

Например:

exec { 'Change-prefix':
  command => "sed -i.bak s/PREFIX=\\\\/jenkins/PREFIX=\\\\/foorbar/g /etc/default/jenkins",
  path    => ["/bin"],           
}

редактировать: ... но, конечно, используя другой разделитель, как Кенни и Иэн предложено, это намного более чистое решение!