I have a need to edit lines in /etc/fstab and add/change fsoptions to lines where a matching volume is found. I have tried using sed and putting found blocks into registers to place them back, but am finding this one a challenge. Perhaps sed is not the best tool - I tried augeas and while it appends it did not replace and also failed if a matching line wasn't found but needed to be added (eg was only visible using the 'mount' command such as /dev/shm).
for example, if /etc/fstab has a line:
/dev/mapper/VolGroup1-tmp /tmp xfs dev,nosuid 0 0
I want to make it
/dev/mapper/VolGroup1-tmp /tmp xfs nodev,nosuid,noexec 0 0
- Note that the volume group in the first block could be any name
- The KEYWORD in the string would (in this example) be /tmp (but careful not to match /var/tmp unless specified)
- The filesystem could be anything (not necessarily xfs)
- Any 'exec' or 'suid' present (for example) needs to be replaced if present and even if not, 'noexec' or 'nosuid' inserted.
- The trailing '0 0' needs to be retained.
I'm sure I am missing an easy way to do this. Using 'mount -o remount,noexec /tmp' doesn't write to /etc/fstab so I guess the only way to make changes persistent is to edit /etc/fstab directly?
I am actually going to wrap the solution in Puppet. The augeas example below fails in 2 regards:
if a line (eg /dev/shm) does not exist in /etc/fstab, it fails
if a line exists and has 'exec' it appends 'noexec' but leaves the exec also
augeas{ "/etc/fstab - ${opt} on ${mount}": context => '/files/etc/fstab', changes => [ "ins opt after /files/etc/fstab/*[file = '${mount}']/opt[last()]", "set *[file = '${mount}']/opt[last()] ${opt}", ], onlyif => "match *[file = '${mount}']/opt[. = '${opt}'] size == 0", notify => Exec["remount_${mount}_${opt}"],
}