首页 > 解决方案 > Puppet - 在每个循环后重新启动服务

问题描述

我正在编写一个 Puppet 模块来强制执行配置并在需要时重新启动服务。我想做这样的事情:

    class app_cfg {
      $app_files = ['file1', 'file2', 'file3']
      $app_files.each |String $file| {
        exec {"sed -i 's/bar/foo/g' $file":
          path   => ['/bin'],
          onlyif => 'grep "bar" $file 2>/dev/null',
          cwd    => '/opt/app/config/',
        }
      } ~>
      service { 'app':
        ensure => running,
        enable => true,
      }
    }

我可以在 exec 中添加“通知”,但我不想为每个文件重新启动我的服务,并且看起来通知链接箭头在每个循环后不起作用。你们知道如何使它工作吗?

非常感谢 :)

我通过在 exec 资源中插入一个 for 循环而不是使用每个循环找到了一种解决方法:

    class app_cfg {
      service { 'app':
        ensure => running,
        enable => true,
      }
      exec {"for file in file1 file2 file3; do sed -i 's/bar/foo/g' \$file; done":
        path   => ['/bin'],
        onlyif => 'grep "bar" $file 2>/dev/null',
        cwd    => '/opt/app/config/',
        provider => shell,
        notify => Service['app']
      }
    }

我仍然对第一个解决方案很好奇!你有没有设法做这样的事情?

谢谢!

标签: servicepuppeteach

解决方案


我可以在 exec 中添加“通知”,但我不想为每个文件重新启动我的服务,并且看起来通知链接箭头在每个循环后不起作用。

重要的是要了解 Puppet 清单中的代码仅描述了如何构建目录,而目录又描述了所需的服务器配置。该目录列出了声明的类和资源、它们的参数和属性以及它们之间的关系。清单中的逻辑不会映射到应用结果目录时执行的操作;它仅反映在对哪些类和资源进行编目,以及它们的参数、属性和关系是什么。

因此,当您在清单中使用其中一个链接箭头时,您是在指示目录构建器记录目录中两个资源之间的关系,而不是应用或刷新资源的显式指令。任何声明的资源都不会被多次应用或刷新的次数超过它被应用的次数。因此,在循环中放置一个适当的链式表达式会非常好,但你不能做的是将Service声明本身放在循环中,因为这会产生它的多个声明。因此,您可以执行以下任何操作:

声明服务(一次),并在循环内的链表达式中使用对它的资源引用:

class app_cfg {
  service { 'app':
    ensure => running,
    enable => true,
  }

  ['file1', 'file2', 'file3'].each |String $file| {
    exec {"sed -i 's/bar/foo/g' $file":
      path   => ['/bin'],
      onlyif => 'grep "bar" $file 2>/dev/null',
      cwd    => '/opt/app/config/',
    } ~> Service['App']
  }
}

如上,但使用适当的资源元参数而不是链式表达式:

class app_cfg {
  service { 'app':
    ensure => running,
    enable => true,
  }

  ['file1', 'file2', 'file3'].each |String $file| {
    exec {"sed -i 's/bar/foo/g' $file":
      path   => ['/bin'],
      onlyif => 'grep "bar" $file 2>/dev/null',
      cwd    => '/opt/app/config/',
      notify => Service['app'],
    }
  }
}

或者在收集器的帮助下声明关系:

class app_cfg {
  ['file1', 'file2', 'file3'].each |String $file| {
    exec {"sed -i 's/bar/foo/g' $file":
      path   => ['/bin'],
      onlyif => 'grep "bar" $file 2>/dev/null',
      cwd    => '/opt/app/config/',
      tag    => 'app_notifier',
    }
  }

  Exec<|tag == 'app_notifier|>
  ~> service { 'app':
    ensure => running,
    enable => true,
  }
}

推荐阅读