A quick tour
This tutorial gives a brief overview of using Augeas, and augtool in particular. It's highly recommended that you follow along on your own; to do so, first download and install Augeas. Then, create a sandbox so that you can safely modify files without affecting your system. The commands below create the sandbox from /etc on your system, but you might want to copy the files from tests/root in the source tarball — all the examples below were run against those files.
export AUGEAS_ROOT=/tmp/augeas-sandbox mkdir $AUGEAS_ROOT sudo cp -pr /etc $AUGEAS_ROOT sudo chown -R $(id -nu):$(id -ng) $AUGEAS_ROOT augtool -b
The -b option tells augtool to preserve the original file with an extension of .augsave whenever it makes a change.
In the augtool shell, type help to get a list of commands. The print command is particularly useful to explore what data is present in the tree. The commands to run can either be typed interactively into augtool (with TAB completion on commands and tree paths), or piped in from standard input.
Adding an entry to /etc/hosts
To warm up, let's do something very simple: adding a new entry to /etc/hosts. In the augtool shell, type the following commands:
set /files/etc/hosts/01/ipaddr 192.168.0.1 set /files/etc/hosts/01/canonical pigiron.example.com set /files/etc/hosts/01/alias[1] pigiron set /files/etc/hosts/01/alias[2] piggy save
The four set commands create four nodes underneath /files/etc/hosts/01, and assign them the values passed as the second argument. The data parsed from a file with full path FILE in the filesystem is stored in the tree underneath /files/FILE; with that the set commands manipulate an entry in the file /etc/hosts. A second hierarchy underneath /augeas/files/FILE contains metadata about the file, such as an indication of any errors encountered when the file was read.
The tree for /etc/hosts puts each host entry into its own subtree, numbered sequentially from 1, so that the first host entry appears under /files/etc/hosts/1, the second under /files/etc/hosts/2, etc. We use the label 01 and put the details of our new host entry underneath /files/etc/hosts/01. This works because reading in a /etc/hosts file will never use labels starting with 0, and tree labels are strings, their numeric value is irrelevant. The order in which host entries are written back to file is determined by the order in which they appear in the tree.
The set command creates non-existant nodes as needed. There is a second command, ins, to create new nodes in the tree that provides more control over where exactly a new node shows up, in particular where in the list of its siblings it appears. Because files are inherently sequential, the order of sibling nodes in the tree matters.
The notation alias[1] and alias[2] tells Augeas to set the value for the first and second child of /files/etc/hosts/01. Both nodes are called /files/etc/hosts/01/alias; the new host entry can be listed with
ls /files/etc/hosts/01
or searched for with
match /files/etc/hosts/*/ipaddr 192.168.0.1
which prints /files/etc/hosts/01/ipaddr.
Running (cd ${AUGEAS_ROOT} && diff -u ./etc/hosts ./etc/hosts.augsave) confirms that /etc/hosts now has one additional entry at the end:
diff -up ./etc/hosts.augsave ./etc/hosts --- ./etc/hosts.augsave +++ ./etc/hosts @@ -4,3 +4,4 @@ #172.31.122.254 granny.watzmann.net granny puppet #172.31.122.1 galia.watzmann.net galia 172.31.122.14 orange.watzmann.net orange +192.168.0.1 pigiron.example.com pigiron piggy
Changing /etc/grub.conf
Modifying a slightly more complex file, /etc/grub.conf [1], follows the same lines as modifying /etc/hosts. One of the big advantages of Augeas is that configuration data is manipulated in the same way, regardless of how it is stored in the native config files.
While the above change to /etc/hosts can be easily achieved with standard shell tools (cat comes to mind), and /etc/hosts in general can be manipulated relatively easily with sed, grep, awk, or tools readily available in most scripting languages, manipulating /etc/grub.conf with those tools is quite a bit harder.
We want to change /etc/grub.conf so that grub boots the second boot entry by default, and remove the third boot record completely. The following two commands do that — you should look at the tree before and after the change using print /files/etc/grub.conf:
set /files/etc/grub.conf/default 1 rm /files/etc/grub.conf/title[3] save
The diff between the old and new file confirms that Augeas changed what was intended:
diff -up ./etc/grub.conf.augsave ./etc/grub.conf --- ./etc/grub.conf.augsave 2008-04-09 16:14:06.000000000 -0700 +++ ./etc/grub.conf 2008-04-15 15:32:09.000000000 -0700 @@ -7,7 +7,7 @@ # kernel /vmlinuz-version ro root=/dev/vg00/lv00 # initrd /initrd-version.img #boot=/dev/sda -default=0 +default=1 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu @@ -19,11 +19,6 @@ title Fedora (2.6.24.3-50.fc8) root (hd0,0) kernel /vmlinuz-2.6.24.3-50.fc8 ro root=/dev/vg00/lv00 initrd /initrd-2.6.24.3-50.fc8.img -title Fedora (2.6.21.7-3.fc8xen) - root (hd0,0) - kernel /xen.gz-2.6.21.7-3.fc8 - module /vmlinuz-2.6.21.7-3.fc8xen ro root=/dev/vg00/lv00 - module /initrd-2.6.21.7-3.fc8xen.img title Fedora (2.6.24.3-34.fc8) root (hd0,0) kernel /vmlinuz-2.6.24.3-34.fc8 ro root=/dev/vg00/lv00
Making sshd accept an additional environment variable
The config file for sshd is deceptively simple, but has some subtle intricacies. One of them are Match blocks at the end of the file, another is the fact that some settings can be repeated in the file, and values are accumulated, and that their values are best viewed as arrays.
To illustrate this, we will add a new environment variable FOO to the AcceptEnv setting in /etc/ssh/sshd_config. The schema that Augeas uses for sshd_config [2] by default maps multiple AcceptEnv lines into multiple tree nodes with the name AcceptEnv, similar to how multiple aliases in /etc/hosts are handled. Since each line contains a list of environment variables, the schema splits that list into separate tree nodes numbered starting at one. The following lines in sshd_config
AcceptEnv LANG LC_CTYPE AcceptEnv LC_IDENTIFICATION LC_ALL
are mapped into a tree
AcceptEnv[1]/1 = "LANG" AcceptEnv[1]/2 = "LC_CTYPE" AcceptEnv[2]/1 = "LC_IDENTIFICATION" AcceptEnv[2]/2 = "LC_ALL"
This allows for very fine-grained access to individual value in the sshd_config file, and preserves enough information so that Augeas can decide which entries go on the same line. To see all AcceptEnv entries, run
print /files/etc/ssh/sshd_config/AcceptEnv/*
To add a new variable FOO at the end of the last AcceptEnv line, we perform
set /files/etc/ssh/sshd_config/AcceptEnv[last()]/01 FOO save
The addition of [last()] to AcceptEnv in the path tells Augeas that we are talking about the last node named AcceptEnv. Augeas requires that for a set the path expression corresponds either to an existing node, or to no node at all (in which case a new node is created). Writing the above command as
set /files/etc/ssh/sshd_config/AcceptEnv/01 FOO
results in an error when there are multiple AcceptEnv entries in the tree. In that case, Augeas can not figure out under which of them you want to put the entry labelled 01.
Again, the above commands lead to the expected diff, the addition of FOO to the last AcceptEnv line:
diff -up ./etc/ssh/sshd_config.augsave ./etc/ssh/sshd_config --- ./etc/ssh/sshd_config.augsave +++ ./etc/ssh/sshd_config @@ -93,7 +93,7 @@ UsePAM yes # Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -AcceptEnv LC_IDENTIFICATION LC_ALL +AcceptEnv LC_IDENTIFICATION LC_ALL FOO #AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no
[1] | some distributions do not have a /etc/grub.conf, but only a /boot/grub/menu.lst or similar. The simplest way to follow these examples is to create a symbolic link $AUGEAS_ROOT/etc/grub.conf that points to the real grub config in your sandbox. In real life, you would change paths like /files/etc/grub.conf/... to /files/boot/grub/menu.lst/... when interacting with Augeas |
[2] | all schemas can be found in the lenses/ subdirectory in the source tarball, which by default is installed into /usr/share/augeas/lenses |