1. ホーム
  2. login

[解決済み] パペットのファイル_行を特定の順序で表示する

2022-02-16 10:15:32

質問

etc/profileに3つのシステムハードニング行を追加しようとしています。

TMOUT=43200
readonly TMOUT
export TMOUT

もちろん、これらの行はこの特定の順序でなければなりませんし、順序がめちゃくちゃになっているファイルも想定しなければなりません。 カスタムプロファイルを持つホストがあり、変更できないので、テンプレートは使えません。そのため、以下の3行を追加できるようにする必要があります。

そこで、マニフェストにこんなことを書きました。

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

間違えましたか、それともオージアスなど他のものに変えなければならないのでしょうか?

ありがとうございました。

解決方法は?

TL;DR

基本的に3つの選択肢があります。順序付けられた依存関係を作ろうとするか(これは本当のPuppetのやり方ではありません)、複合ステートメントを作るか、あるいは /etc/profile.d ディストリビューションがサポートしている場合 これを処理する唯一の"best"な方法はありませんが、複合ステートメントまたは宣言がおそらくあなたにとって最もシンプルな解決策です。

順序付き依存関係

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互換のシェルのほとんどは(すべてではないにしても)複合文に対応しているはずなので、単一のアトミックな行の操作のために順序を省略する方がよいでしょう。例えば

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

もっといいのは、シェルの 宣言 を使えば、一回の操作ですべてを行うことができます! 例えば

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

注:readonly変数は、readonly属性を直接設定しないサブシェルでも代入可能です。これはあくまでも、その方法です。

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 はベンダーごとに異なるため、profile.d のスクリプトをソースとする順序は異なる場合があります。通常、profile.d のスクリプトのソースはメインの /etc/profile スクリプトが存在し、同じ値を設定するスクリプトが複数存在すると、結果が非決定的になることがあります。