Puppet file_line按特定顺序排列

时间:2017-09-04 08:46:12

标签: login environment-variables sh puppet

我试图在/ etc / profile中添加三个系统强化线:

TMOUT=43200
readonly TMOUT
export TMOUT

当然这些行需要按照这个特定的顺序排列,而且我还需要预期文件混乱并且顺序错误。 我无法使用模板,因为有些主机具有无法更改的自定义配置文件。所以我必须能够追加这三行

所以我在清单中写了这个:

file_line { 'TMOUT':
  path     => '/etc/profile',
  ensure   => present,
  line     => 'TMOUT=43200',
  multiple => true,
  before   => 'readonly TMOUT',
  match    => '^TMOUT',
}
file_line { 'readonly TMOUT':
  path     => '/etc/profile',
  ensure   => present,
  line     => 'readonly TMOUT',
  multiple => true,
  before   => 'export TMOUT',
  after    => '^TMOUT=43200',
  match    => '^readonly TMOUT',
}
file_line { 'export TMOUT':
  path     => '/etc/profile',
  ensure   => present,
  line     => 'export TMOUT',
  multiple => true,
  after    => '^readonly TMOUT',
  match    => '^export TMOUT',
}

Puppet以正确的顺序创建行,但是当我编辑文件并更改顺序时,它会在重新运行期间得到纠正,例如

readonly TMOUT
export TMOUT
TMOUT=43200

我是否犯了错误,或者我必须切换到像Augeas这样的其他东西吗?

提前致谢

2 个答案:

答案 0 :(得分:3)

TL; DR

您基本上有三个选项:尝试创建有序依赖项(实际上不是Puppet方式),创建复合语句,或者如果您的发行版支持它,请使用 /etc/profile.d 。虽然没有单一的“最佳”方法来处理这个问题,但复合语句或声明可能是最简单的解决方案。

Ordered Dependencies

除非您明确声明依赖项,否则Puppet不保证对大多数操作进行排序。以下是未经测试的,但可能适合您。

file_line { 'set TMOUT':
  ensure => present,
  path   => '/etc/profile',
  line   => 'TMOUT=43200',
  match  => '^TMOUT',
} ->
file_line { 'export TMOUT':
  ensure => present,
  path   => '/etc/profile',
  line   => 'export TMOUT',
  after  => '^TMOUT=',
} ->
file_line { 'set TMOUT as readonly':
  ensure => present,
  path   => '/etc/profile',
  line   => 'readonly TMOUT',
  after  => '^export TMOUT',
}

这应该做你想要的,但比它需要的更脆弱。有更强大的选择。

复合语句和变量声明

大多数(如果不是全部)与Bourne兼容的shell应该支持复合语句,因此最好不要跳过单个原子线操作的排序。例如:

file_line { 'profile TMOUT':
  ensure => present,
  path   => '/etc/profile',
  line   => 'TMOUT=43200; export TMOUT; readonly TMOUT',
  match  => '^TMOUT',
}

更好的是,使用shell的声明 synax在一次操作中完成所有操作!例如:

file_line { 'profile TMOUT':
  ensure => present,
  path   => '/etc/profile',
  line   => 'declare -r -x TMOUT=43200',
  match  => '^TMOUT',
}

注意:readonly变量仍然可以分配给不直接设置readonly属性的子shell。这就是它的工作方式。

将文件放入Profile.d

在支持它的发行版上,使用 /etc/profile.d 几乎总是比在 / etc / profile 这样的单一脚本中进行修改更好。它也不太可能受到其他脚本,系统更新等的破坏。但是,我有一些注意事项,我将在下面说明。

# Create your snippet in the /etc/profile.d directory.
file {'/etc/profile.d/tmout.sh':
  ensure => present,
  content => "TMOUT=43200\nexport TMOUT\nreadonly TMOUT",
} ->

# Remove the lines in /etc/profile if they exist.
file_line { 'profile TMOUT':
  ensure            => absent,
  path              => '/etc/profile',
  match             => 'TMOUT',
  match_for_absence => true,
  multiple          => true,
}

这里有一些注意事项:

  1. 存在一种微妙的竞争条件(即使是依赖链接),因为这些变化是连续的而不是原子的。可能有一个小窗口,其中TMOUT在多个位置定义。
  2. 因为profile.d是特定于供应商的,所以除非您对其进行配置,否则它可能根本不受支持(甚至可能不存在)。查看您的分发文档。
  3. 同样,由于profile.d是特定于供应商的,因此profiled中脚本的来源顺序可能会有所不同。它们通常来自主 / etc / profile 脚本之后,并且存在多个设置相同值的脚本会使结果不确定。

答案 1 :(得分:0)

你期待的File_line比它能给你的更多。该资源代表文件的单独一行。相应的物理线路存在或不存在。没有“现在但没有秩序”的感觉,因为这不是线本身的特征;它将是包含该行的文件的特征。

您尝试获取所需订单时使用的beforeafter元参数不会执行您的想法。它们对所有资源都是通用的,它们会影响资源应用于目标计算机的顺序。这是一个意想不到的副作用,当您使用这些元参数时,在某些情况下会生成所需的行排序。完全可以预期它们不会导致现有行在文件中重新排序。

你需要另一种方法。也许Augeas会做你想做的事。您也可以考虑编写几个脚本 - 一个用于测试文件以查看是否需要修改,另一个用于修复它们 - 并使用Exec的脚本。