2

I have a transient prelink process populating our audit log, but we're not sure what the process is. The error log gives us the PID, but it disappears pretty much instantly, as the process finishes when it errors, I guess.

What I want to do is tail the log, grep out the PID, and pump that into a 'ps -p', or a 'ps -ef | grep PID'.

What I've got so far is:

ps -p $(tail -f /var/log/audit/audit.log | grep 'comm="prelink"' | grep -o 'pid=[0-9]* ' | grep -o [0-9]*)

But I think the shell expansion isn't updating, i.e. I run the command and the PID it finds from the last entry of the log is, say 1234, then ps is only ever searching for that, and it doesn't update.

I've tried variations around infinitely looping the output of the tail into PS, or into a grep of PS, but I'm not getting anywhere. I'm running tail -f of the log on its own in another window to see when it updates, and it definitely is, but the command to scrape PS for that PID isn't reacting.

Can anyone suggest a way to achieve what I'm trying to do?

Also, is there a really simple and better and obvious way to do this? I'm not super experienced and I have a habit of massively over-complicating things, so if you've got a "Why don't you just X", feel free to throw it in!

Thanks heaps! B.

  • I guess you completely misunderstand what your command line does. Please clarify: You want to execute just one command, and every time when a new matching line occurs in the log then ps shall be run again? – Hauke Laging Nov 24 '14 at 2:03
  • Yeah, that's right. I want to watch the log file for PID's that match the search, and execute PS to find out which process that PID belongs to, before the process finishes. – JediWombat Nov 24 '14 at 2:28
1

You should always quote expressions like [0-9]*.

tail -f /var/log/audit/audit.log |
  grep --line-buffered 'comm="prelink"' |
  grep --line-buffered -o 'pid=[0-9]* ' |
  grep --line-buffered -o '[0-9]*' |
  while read pid; do
    ps -p "$pid"
  done

tail -f doesn't buffer its output. For other applications unbuffer or stdbuf solve the problem.

  • 2
    On my Debian, tail -f seems to be buffered. This won't start printing until after ~350 or so lines have been added. – terdon Nov 24 '14 at 4:52
  • Worked a treat! The process is so fast that a lot of the calls to ps -p don't find anything, but I'm getting results every now and again, and that lets me see what's triggering the log entries. Thanks heaps :) B. – JediWombat Nov 25 '14 at 23:00
0

You could always just run it in an endless loop and avoid buffering issues. Since you presumably won't be running this for long and can stop it manually, just run

while true; do
    ps -p $( tail -n1 /var/log/audit/audit.log | 
             grep -oP 'comm="prelink".*pid=\K[0-9]*' ) 2>/dev/null

That will constantly print the last line of the file, extract the PID, if any, and run ps -p on it. It will complain if there is no PID so you need to redirect the error output. I also combined your greps into a single command. The \K is a PCRE feature (enabled by -P) that means "forget everything matches so far". It is very useful combined with -o to print only parts of a match.

The above is not elegant and it will spam your CPU with many processes but it should be enough for a quick check.

  • "That will constantly print the last line of the file". Indeed. Quite useless, isn't it? – Hauke Laging Nov 24 '14 at 4:26
  • @HaukeLaging this will be run in an endless loop. I don't know how the OP's file will be populated and it seems to be reasonable to only grab the last line. Removing the -n1 will search the last few lines if that will make you feel better. Also, please remember to be nice. – terdon Nov 24 '14 at 4:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.