Ben Swinburne
Ben Swinburne

Reputation: 26477

Update var in ini file using bash

I am attempting to write a bash script to configure various aspects of a server. The context here is replacing a value of a variable in a conf file (ini format) with another value.

The context is

[ssh-iptables]

enabled = false

And I simply need to change false to true.

Typically I'd just do this with a simple bit of sed

sed -i 's/^enabled = false/enabled = true/g' /etc/fail2ban/jail.conf

But enabled = false exists in multiple places.

I've tried using awk with no success

awk -F ":| " -v v1="true" -v opt="enabled" '$1 == "[ssh-iptables]" && !f {f=1}f && $1 == opt{sub("=.*","= "v1);f=0}1' /etc/fail2ban/jail.conf

The above was sourced from this forum thread but I don't really have enough understanding of how to use it in scripts to make it work. All it seems to do is the equivalent of cat /etc/fail2ban/jail.conf

I have found a few other scripts which are considerably longer which isn't ideal as this will happen to loads of ini files so I'm hoping someone can help me correct the above code or point me in the right direction.

Apologies if this belongs on ServerFault, but as it's scripting rather than the intricacies of server configuration itself I figured here might be more apt.

Upvotes: 21

Views: 20868

Answers (4)

Lauskin
Lauskin

Reputation: 450

If you are open to use external applications, you could be interested into the use of crudini.

Example:

[oauth2provider]
module = SippoServiceOAuth2Provider
backend[] = none
wiface = public

; [calldirection]
; module = SippoServiceCallDirection
; backend[] = none
; wiface = internal

A standard grep will not filter commented exceptions.

With crudini things for consulting, setting and modify are easier:

$ crudini --get /myproject/config/main.ini oauth2provider wiface
public
$ crudini --get /myproject/config/main.ini calldirection wiface
Section not found: calldirection

I was on a bash-only app and moved to this approach. Just a suggestion.

Regards,

Upvotes: 17

PaulProgrammer
PaulProgrammer

Reputation: 17680

You might consider using m4 instead of sed in this case. This uses variable replacement and I think keeps the file looking readable. Your m4 template might look like this:

[ssh-iptables]
enabled=SSH_IPTABLES_ENABLED

Now, you call m4 with the following parameters (which can be called from a bash script):

m4 -DSSH_IPTABLES_ENABLED=true input.m4 > output.ini

or:

m4 -DSSH_IPTABLES_ENABLED=false input.m4 > output.ini

This is an overly simple way of using m4, if you read about it you'll find you can do some really nifty things (this is the infrastructure upon which autoconf/automake was initially designed).

Upvotes: 3

Dan Fego
Dan Fego

Reputation: 14014

Assuming your format is that there are no square-bracket lines (like [ssh-iptables]) within sections, I would use your solution above (with sed) but restrict the query to within that block like so:

sed -i '/^\[ssh-iptables\]$/,/^\[/ s/^enabled = false/enabled = true/' /etc/fail2ban/jail.conf

The extra part at the beginning tells the following substitution statement to only run between the line that is [ssh-iptables] and the next one that starts with a [. It uses two regular expressions separated by a comma which indicate the bounds.

Upvotes: 30

jim mcnamara
jim mcnamara

Reputation: 16389

awk '/^[ssh-iptables/ {ok=1}
     ok==1 && $0="enabled = false" {print "  enabled = true"; ok=0 ; next}
     {print $0} ' infile > tmp
     mv tmp infile

Upvotes: 1

Related Questions