3

I want to check the auth.log file for accepted sshd connections and execute an action if any are found.

Here is my code:

tail -f /var/log/auth.log | awk '{ if($0 ~ /sshd/ && $0 ~ /Accepted/) { system("echo FOUND") } }'

For some reason, this produces no output. Can somebody explain why?

2 Answers 2

5

I think that your problem is related to the bufferisation of tail -f:

~$ tail auth.log | awk '{ if($0 ~ /sshd/ && $0 ~ /Accepted/) { system("echo FOUND") } }'
FOUND
FOUND

It works with tail, but fails with tail -f:

~$ tail -f auth.log | awk '{ if($0 ~ /sshd/ && $0 ~ /Accepted/) { system("echo FOUND") } }'
^C

A workaround you could use, is using a while loop to read each line of tail -f:

~$ tail -f auth.log | while read line
> do
>     echo $line | awk '{ if($0 ~ /sshd/ && $0 ~ /Accepted/) { system("echo FOUND")} }'
> done
FOUND
FOUND

--

Searching man awk for buffer, I found the -W option (but this is a mawk version…):

-W interactive

    sets unbuffered writes to stdout and line buffered reads from stdin. Records from stdin are lines regardless of the value of RS.

also:

mawk accepts abbreviations for any of these options, e.g., “-W i” and “-Wi” …

~$ tail -f auth.log | awk  -Wi  '/sshd/ && /Accepted/ {system("echo FOUND")}'
FOUND
FOUND
1
  • I solved it via the -Wi option. Thanks a lot!
    – Chris
    Jun 9, 2015 at 10:31
3

You can also use awk's fflush() call to flush output:

tail -f /var/log/auth.log | 
    awk '{ if($0 ~ /sshd/ && $0 ~ /Accepted/) { fflush(); system("echo FOUND") } }'

That said, your awk is needlessly complex. All you need is:

tail -f /var/log/auth.log | awk '/sshd/ && /Accepted/{ fflush(); print "FOUND"}'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .