3

I'd like to ensure that I have the lines ...

root: /dev/null
greenman: /dev/null

... in my /etc/aliases file and I have been learning about augtool. I know I could do something like this with augtool ...

$ sudo augtool set /files/etc/aliases/15/name greenman

... but I do not like hard coding the 15. It is quite possible on some systems greenman: /dev/null might be the 10th name/value pair. Is there a way to avoid using a number in /files/etc/aliases/15/name ?

Thanks

Red Cricket
  • 462
  • 2
  • 7
  • 20

1 Answers1

4

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.

raphink
  • 11,337
  • 6
  • 36
  • 47