Working with seq
entries (these numbered entries, such as 15
in your case) in Augeas can be a little bit tricky.
Using augtool
still
You can make yourself an augtool script that looks like this:
#!/usr/bin/augtool -sf
# First, match /etc/aliases, only if there's no "greenman" entry yet
# This will define a `$yellowwoman` variable which will contain `/etc/aliases`,
# but only if there is no "greenman" entry yet (i.e. the count of the
# "greenman" entries is 0)
defvar yellowwoman /files/etc/aliases[count(*[name="greenman"])=0]
# Add the greenman entry at the end
# (using `01`, which is never used automatically in `seq` entries)
set $yellowwoman/01/name greenman
# Now set the value for the "greenman" entry,
# which you can be sure exists.
# Don't reuse the `$yellowwoman` variable, otherwise you'll
# only set the value when "greeman" wasn't there yet
# By selecting the "greenman" entry, you will always set the value
# even if the entry already existed in the file
set /files/etc/aliases/*[name="greenman"]/value /dev/null
The shebang (#!/usr/bin/augtool -sf
) uses -s
to automatically save after making the changes, and -f
to take a file with commands, making it a self-executable script, so you can just make the file execuable and run it:
$ chmod +x greenman.augtool
$ sudo ./greenman.augtool
Saved 1 file(s)
$ sudo ./greenman.augtool # it should be idempotent, too
If you don't want to make the script executable, you can also pass it to augtool
:
$ sudo augtool --autosave --file greenman.augtool
Saved 1 file(s)
And if you don't want to use --autosave
, you can add save
as the last line of the script.
Using a "real" programming language
Bash is nice, but coping with its limits can lead to complex solutions. Augeas has lots of bindings in many languages. Just pick one and it will get easier to write your code, because you will be able to use a persistent Augeas handler. Here is an example with Ruby:
#!/usr/bin/env ruby
require 'augeas'
Augeas.open do |aug|
if aug.match('/files/etc/aliases/*[name="greenman"]').empty?
# Create a new "greeman" entry
aug.set('/files/etc/aliases/01/name', 'greenman')
end
# Set the value
aug.set('/files/etc/aliases/*[name="greenman"]/value', '/dev/null')
# Commit your changes
aug.save!
end
Using Puppet
In Puppet, the best solution is to rely on the mailalias
type with the augeas
provider from augeasproviders. It uses the Augeas Ruby library to safely edit /etc/aliases
:
mailalias { 'greenman':
ensure => present,
recipient => '/dev/null',
provider => augeas,
}
Note: mailalias
is a standard Puppet type, but the default provider doesn't use Augeas.