7

Assumming that I have the following in the /etc/syslog.conf file:

# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.*                         /dev/console

I want to change it to kern.* /var/log/kern.log to get the human-readable timestamp for kernel log.

Puppet can do it:

class syslog::config {
    file { "/etc/syslog.conf":
        ensure  => present,
        source  => "puppet:///modules/syslog/syslog.conf",
        require => Class["syslog::install"],
        notify  => Class["syslog::service"],
    }
}

or I can also use the sed -i.

With Augeas, I can append this line to the end of file:

class syslog::config {
    augeas { "syslogkern":
        context => "/files/etc/syslog.conf",
        changes => [
            "set entry[last()+1]/selector/facility kern",
            "set entry[last()]/selector/level *",
            "set entry[last()]/action/file '/var/log/kern.log'",
        ],
    }
}

or modify the destination:

class syslog::config {
    augeas { "syslogkern":
        context => "/files/etc/syslog.conf",
        onlyif  => "get #comment[3] == 'kern.*\t\t\t\t\t\t\t/dev/console'",
        changes => [
            "set #comment[3] 'kern.*\t\t\t\t\t\t\t/var/log/kern.log'",
        ],
    }
}

But how do I uncomment this line?


UPDATE

Here's what I've been trying to insert a line after #comment[3]:

augtool> ins facle after /files/etc/syslog.conf/#comment[3]
augtool> set /files/etc/syslog.conf/facle/selector/facility kern
augtool> set /files/etc/syslog.conf/facle/selector/level *
augtool> set /files/etc/syslog.conf/facle/action/file /var/log/kern.log

or:

augtool> ins facle after /files/etc/syslog.conf/#comment[3]
augtool> set /files/etc/syslog.conf/facle[last()] kernlog
augtool> set /files/etc/syslog.conf/facle[. = 'kernlog']/selector/facility kern
augtool> set /files/etc/syslog.conf/facle[. = 'kernlog']/selector/level *
augtool> set /files/etc/syslog.conf/facle[. = 'kernlog']/action/file /var/log/kern.log

but it didn't work:

augtool> save
error: Failed to execute command
error: saving failed (run 'print /augeas//error' for details)
augtool> print /augeas//error
/augeas/files/etc/syslog.conf/error = "put_failed"
/augeas/files/etc/syslog.conf/error/path = "/files/etc/syslog.conf"
/augeas/files/etc/syslog.conf/error/lens = "/usr/share/augeas/lenses/dist/syslog.aug:243.18-.51:"
/augeas/files/etc/syslog.conf/error/message = "Failed to match \n    ({ } | { /#comment/ = /[^\\001-\\004\\t\\n !+-][^\\001-\\004\\n]*[^\\001-\\004\\t\\n ]|[^\\001-\\004\\t\\n !+-]/ } | { /entry/ })*({ /program/ } | { /hostname/ })*\n  with tree\n    { \"#comment\" = \"Log all kernel messages to the console.\" } { \"#comment\" = \"Logging much else clutters up the screen.\" } { \"#comment\" = \"kern.*\t\t\t\t\t\t\t/var/log/kern.log\" } { \"facle\" = \"kernlog\" } { \"entry\" } {  } { \"#comment\" = \"Log anything (except mail) of level info or higher.\" } { \"#comment\" = \"Don't log private authentication messages!\" } { \"entry\" } {  } { \"#comment\" = \"The authpriv file has restricted access.\" } { \"entry\" } {  } { \"#comment\" = \"Log all the mail messages in one place.\" } { \"entry\" } {  } {  } { \"#comment\" = \"Log cron stuff\" } { \"entry\" } {  } { \"#comment\" = \"Everybody gets emergency messages\" } { \"entry\" } {  } { \"#comment\" = \"Save news errors of level crit and higher in a special file.\" } { \"entry\" } {  } { \"#comment\" = \"Save boot messages also to boot.log\" } { \"entry\" } {  } {  } { \"#comment\" = \"INN\" } {  } { \"entry\" } { \"entry\" } { \"entry\" }"
quanta
  • 50,327
  • 19
  • 152
  • 213

2 Answers2

5

{,Un}commenting is a complex matter with Augeas, because of its nature. The short answer is that Augeas cannot {,un}comment nodes currently.

The reason (and proposed solutions) is detailed in this ticket.

As for the reason why your insert fails, it's because you created a facle node instead of an entry node. facle is not a known node name in syslog.aug.

So here is something you could do instead:

augtool> print /files/etc/syslog.conf/
/files/etc/syslog.conf
/files/etc/syslog.conf/#comment[1] = "titi"
/files/etc/syslog.conf/#comment[2] = "kern.*                         /dev/console"
/files/etc/syslog.conf/#comment[3] = "toto"
augtool> defvar kerncomment /files/etc/syslog.conf/#comment[. =~ regexp('kern.* +/dev/console')][count(/files/etc/syslog.conf/entry[selector/facility = "kern" and selector/level = "*" and action/file = "/var/log/kern.log"]) = 0]
augtool> ins entry after $kerncomment
augtool> defvar kernentry /files/etc/syslog.conf/entry[preceding-sibling::*[1][$kerncomment]]
augtool> set $kernentry/selector/facility kern
augtool> set $kernentry/selector/level *
augtool> set $kernentry/action/file /var/log/kern.log
augtool> rm $kerncomment
augtool> print /files/etc/syslog.conf/
/files/etc/syslog.conf
/files/etc/syslog.conf/#comment[1] = "titi"
/files/etc/syslog.conf/entry
/files/etc/syslog.conf/entry/selector
/files/etc/syslog.conf/entry/selector/facility = "kern"
/files/etc/syslog.conf/entry/selector/level = "*"
/files/etc/syslog.conf/entry/action
/files/etc/syslog.conf/entry/action/file = "/var/log/kern.log"
/files/etc/syslog.conf/#comment[3] = "toto"
augtool> save
Saved 1 file(s)
augtool> 

The first line ensures this change is idempotent. This can be simplified if you use Puppet: you can avoid the complexity of the first line by using onlyif.

raphink
  • 11,337
  • 6
  • 36
  • 47
  • One more question: how can I keep vertical align by inserting some tabs before `/var/log/kern.log`? `\t` didn't work. – quanta Dec 16 '11 at 04:02
  • You can't. Spaces and newlines are removed by Augeas to produce the tree, and there is no way to control them through the API. When you modify an existing entry, they are kept the way they were, and when you create a new entry, the default separator is used. – raphink Dec 16 '11 at 08:46
2

There is not a simple "uncomment this line" facility in Augeas AFAIK. You can use ins to locate the existing comment, insert the new entry with the set commands as you have and then remove the comment.

Per request, here's an example of how I set up "serial" and "terminal" for a serial console for GRUB:

augeas { "grub-serial-ttyS${portnum}":
   context => "/files/etc/grub.conf",
   changes => [
       'rm serial',
       'ins serial after timeout',
       "set serial/unit '${portnum}'",
       "set serial/speed '${portspeed}'",
       'rm terminal',
       'ins terminal after serial',
       "set terminal/timeout '5'",
       "clear terminal/console",
       "clear terminal/serial",
   ],
}

The only caveat is that timeout has to exist.

Actually, I'm not sure this really is a good example, but here it is anyway.

Wil Cooley
  • 361
  • 3
  • 10