Shell-Script

使用腳本編輯類似 INI 的文件

  • December 31, 2018

我正在編寫一個腳本來自動在 Docker 中設置 Puppet 代理配置文件。

基本上,我需要確保以下部分位於/etc/puppet/puppet.conf

[agent]
server=$PUPPETMASTER_HOSTNAME
masterport=$PUPPETMASTER_PORT

到目前為止,我在 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

問題應該很明顯了。如果 Puppet 配置已經指定了配置,我只是附加了另一個[agent]部分,這很糟糕。

我可以打開條件邏輯(即:如果存在則 grep,如果存在則用 sed 重寫它),但是有沒有辦法從命令行進行編輯?我想基本上執行一個命令,上面寫著“如果沒有代理部分,請添加它,然後確保伺服器和主埠在該部分中設置為正確的值。”

我知道像這樣的結構化工具存在於 XML 中,但是 INI 樣式的文件呢?

以下是一些腳本範例。這些是最低限度的,並且不會為錯誤檢查、命令行選項等而煩惱。我已經指出我是否自己執行了腳本來驗證它的正確性。

紅寶石

inifile為此腳本安裝ruby​​gem。此腳本經過測試

#!/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

用法:

$ chmod 700 ~/config.rb
$ sudo ~/config.rb     # or, if using rvm, rvmsudo ~/config.rb

Perl

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();

用法:

$ chmod 700 ~/config.pl
$ sudo ~/config.pl

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; }

用法:

$ awk -f ~/config.awk < /etc/puppet/puppet.conf > /tmp/puppet.conf
$ sudo mv /tmp/puppet.conf /etc/puppet/puppet.conf

看看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"

或單個原子呼叫,例如:

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

crudini --merge /etc/puppet/puppet.conf

引用自:https://unix.stackexchange.com/questions/137643