使用脚本编辑类似 INI 的文件

Naf*_*Kay 6 configuration shell-script text-processing

我正在编写一个脚本来在 Docker 中自动设置 Puppet 代理配置文件。

基本上,我需要确保以下部分在/etc/puppet/puppet.conf

[agent]
server=$PUPPETMASTER_HOSTNAME
masterport=$PUPPETMASTER_PORT
Run Code Online (Sandbox Code Playgroud)

到目前为止,我在 Puppet 代理 runit 脚本中一直在做的是:

function write_puppet_config () {
    read -d '' puppet_config <<EOF
[agent]
server=$1
masterport=$2
EOF

    echo -e "$puppet_config" >> /etc/puppet/puppet.conf
}

# default puppet master port is 8410
test -z "$PUPPET_MASTER_TCP_PORT" && export PUPPET_MASTER_TCP_PORT="8410"

# if there is a puppet master host defined, rewrite the config to match
if [ ! -z "$PUPPET_MASTER_TCP_HOST" ]; then 
    write_puppet_config "$PUPPET_MASTER_TCP_HOST" "$PUPPET_MASTER_TCP_PORT"
fi
Run Code Online (Sandbox Code Playgroud)

问题应该很明显了。如果 Puppet 配置已经指定了配置,我只是附加了另一[agent]部分,这很糟糕。

我可以打开条件逻辑(即:grep,如果它在那里,然后用 sed 重写它),但是有没有办法从命令行进行编辑?我想基本上运行一个命令,上面写着“如果没有代理部分,请添加它,然后确保在该部分中将服务器和主端口设置为正确的值。”

我知道对于 XML 存在这样的结构化工具,但是 INI 样式的文件呢?

Pád*_*ady 21

看看crudini,这是一个为此设计的shell工具

conf=/etc/puppet/puppet.conf
crudini --set "$conf" agent server "$PUPPET_MASTER_TCP_HOST"
crudini --set "$conf" agent masterport "$PUPPET_MASTER_TCP_PORT"
Run Code Online (Sandbox Code Playgroud)

或单个原子调用,如:

echo "
[agent]
server=$1
masterport=$2" |

crudini --merge /etc/puppet/puppet.conf
Run Code Online (Sandbox Code Playgroud)


Jus*_*n C 5

下面是一些脚本示例。这些是最低限度的,不用担心错误检查、命令行选项等。我已经指出我是否自己运行过脚本来验证它的正确性。

红宝石

inifile为这个脚本安装rubygem。这个脚本已经过测试

#!/usr/bin/env ruby
# filename: ~/config.rb

require 'inifile'

PUPPETMASTER_HOSTNAME='hello'
PUPPETMASTER_PORT='world'

ini = IniFile::load('/etc/puppet/puppet.conf')
ini['agent']['server'] = PUPPETMASTER_HOSTNAME
ini['agent']['masterport'] = PUPPETMASTER_PORT
ini.save
Run Code Online (Sandbox Code Playgroud)

用法:

$ chmod 700 ~/config.rb
$ sudo ~/config.rb     # or, if using rvm, rvmsudo ~/config.rb
Run Code Online (Sandbox Code Playgroud)

珀尔

Config::IniFiles使用cpan或您的操作系统包管理器进行安装(如果有可用的包)。该脚本未经测试,因为我已停止perl 在我的系统上使用。它可能需要一些工作,欢迎更正。

#!/usr/bin/env perl
# filename: ~/config.pl

use Config::IniFiles;

my $PUPPETMASTER_HOSTNAME='perl';
my $PUPPETMASTER_PORT='1234';

my $ini = Config::IniFiles->new(-file => '/etc/puppet/puppet.conf');

if (! $ini->SectionExists('agent')) {
    $ini->AddSection('agent');
}

if ($ini->exists('agent', 'server')) {
    $ini->setval('agent', 'server', $PUPPETMASTER_HOSTNAME);
}
else {
    $ini->newval('agent', 'server', $PUPPETMASTER_HOSTNAME);
}

if ($ini->exists('agent', 'masterport')) {
    $ini->setval('agent', 'masterport', $PUPPETMASTER_PORT);
}
else {
    $ini->newval('agent', 'masterport', $PUPPETMASTER_PORT);
}

$ini->RewriteConfig();
Run Code Online (Sandbox Code Playgroud)

用法:

$ chmod 700 ~/config.pl
$ sudo ~/config.pl
Run Code Online (Sandbox Code Playgroud)

awk

该脚本对 Bash 和 *nix 更加友好,并使用 *nix OS 的通用实用程序awk. 这个脚本已经过测试

#!/usr/bin/env awk
# filename: ~/config.awk

BEGIN {
    in_agent_section=0;
    is_host_done=0;
    is_port_done=0;
    host = "awk.com";
    port = "4567";
}

in_agent_section == 1 {
    if ($0 ~ /^server[[:space:]]*=/) {
        print "server="host;
        is_host_done = 1;
        next;
    }
    else if ($0 ~ /^masterport[[:space:]]*=/) {
        print "masterport="port;
        is_port_done = 1;
        next;
    }
    else if ($0 ~ /^\[/) {
        in_agent_section = 0;
        if (! is_host_done) {
            print "server="host;
        }
        if (! is_port_done) {
            print "masterport="port;
        }
    }
}

/^\[agent\]/ {
    in_agent_section=1;
}

{ print; }
Run Code Online (Sandbox Code Playgroud)

用法:

$ awk -f ~/config.awk < /etc/puppet/puppet.conf > /tmp/puppet.conf
$ sudo mv /tmp/puppet.conf /etc/puppet/puppet.conf
Run Code Online (Sandbox Code Playgroud)