aurelio
aurelio

Reputation: 13

How to add "date" as column in a log file with Awk command

I'm trying to build my own hardware monitor and I'm stuck trying to put timestamps in my log file.

I'm using "ps axu" to get results and trying to use awk to filter results before sending them to a file.

Using the command below:

ps axu |awk 'NR==1 {print $0}; $3 > 0'

I get this result:

USER     PID  %CPU %MEM   VSZ   RSS   TTY      STAT START   TIME COMMAND
user+    1421  0.1  0.9 304212  36384 tty2     Sl+  Oct27   4:11 /usr/lib/
user+    1584  0.1  2.0 3626228 82152  ?       Ssl  Oct27   5:43 /usr/bin/
user+    2096  0.7 14.6 4197076 587032 ?       Sl   Oct27  22:14 /usr/lib/
user+    2248  0.5  8.4 3147328 340168 ?       Sl   Oct27  14:48 /usr/lib/
user+    2272  1.0 14.6 3298264 587372 ?       Sl   Oct27  30:47 /usr/lib/
user+   18658  0.1  0.0  12232  2468  pts/1    S+   Oct28   1:03 top

I want to send this to a new file adding one more column with a timestamp like this:

USER     PID  %CPU %MEM   VSZ   RSS   TTY      STAT START   TIME COMMAND   TIMESTAMP
user+    1421  0.1  0.9 304212  36384 tty2     Sl+  Oct27   4:11 /usr/lib/ Thu 29 Oct 2020 09:00:42 AM EDT
user+    1584  0.1  2.0 3626228 82152  ?       Ssl  Oct27   5:43 /usr/bin/ Thu 29 Oct 2020 09:00:42 AM EDT
user+    2096  0.7 14.6 4197076 587032 ?       Sl   Oct27  22:14 /usr/lib/ Thu 29 Oct 2020 09:00:42 AM EDT
user+    2248  0.5  8.4 3147328 340168 ?       Sl   Oct27  14:48 /usr/lib/ Thu 29 Oct 2020 09:00:42 AM EDT
user+    2272  1.0 14.6 3298264 587372 ?       Sl   Oct27  30:47 /usr/lib/ Thu 29 Oct 2020 09:00:42 AM EDT
user+   18658  0.1  0.0  12232  2468  pts/1    S+   Oct28   1:03 top       Thu 29 Oct 2020 09:00:42 AM EDT

I tried to use awk to do this but I'm getting some weird results when executing the command "date" and passing it as a parameter to awk.

This adds a column with "0" as result:

ps axu |awk 'NR==1 {print $0}; $3 > 0'|awk '{print $0, system(date) }'

And this adds the timestamp in a new line instead of a new column:

ps axu |awk 'NR==1 {print $0}; $3 > 0'|awk -v var1=date '{print $0 system(var1) }'

Upvotes: 1

Views: 720

Answers (3)

Hielke Walinga
Hielke Walinga

Reputation: 2845

I you have gawk you can make use of the gettime extension it provides.

ps axu | gawk -i gettime 'NR==1{print $0, "TIMESTAMP"} $3 > 0{print $0, getlocaltime()}'

Otherwise you can make use of the pipe

ps axu | awk 'NR==1{print $0, "TIMESTAMP"} $3 > 0{"date"|getline d; print $0, d}'

At last a solution without awk

paste <(ps axu) <(echo "TIMESTAMP"; yes `date`) | sed -n '/^\s/q;p'

Upvotes: 0

RavinderSingh13
RavinderSingh13

Reputation: 133458

Could you please try following written and tested in GNU awk, using systime and strftime functions of awk.

ps axu | 
awk '
NR==1 {print;next}
$3 > 0{
  print $0,strftime(" %a %d %b %Y %H:%M:%S %p %Z", systime())
}' 

Explanation: Adding detailed explanation for above solution.

ps axu |                 ##Running ps axu command to get the process in system. Sending its output as standard input to awk command.
awk '                    ##Starting awk program from here.
NR==1 {print;next}       ##If its header/first line then simply print it and move cursor to next line.
$3 > 0{                  ##Checking condition if 3rd field is greater than 0 then do following.
  print $0,strftime(" %a %d %b %Y %H:%M:%S %p %Z", systime())  ##Using systime function to get time in mentioned different options manner with strftime.
}' 


%a --> The locale’s abbreviated weekday name.
%d --> The day of the month as a decimal number (01–31).
%b --> The locale’s abbreviated month name.
%Y --> The full year as a decimal number (e.g. 2011).
%H --> The hour (24-hour clock) as a decimal number (00–23).
%M --> The minute as a decimal number (00–59).
%S --> The second as a decimal number (00–60).
%p --> The locale’s equivalent of the AM/PM designations associated with a 12-hour clock.
%Z --> The time zone name or abbreviation; no characters if no time zone is determinable.

Upvotes: 1

Daweo
Daweo

Reputation: 36390

This adds a column with "0" as result:

ps axu |awk 'NR==1 {print $0}; $3 > 0'|awk '{print $0, system(date) }'

AWK's system does return command's (in this case: date) exit status (in this case: 0 i.e. everything ok). system is not right tool if you are interesting in output of command.

GNU AWK has own Time Functions which allow you to get what you want - systime() gives second since start of epoch, strftime allows you to format that into human readable form, so for example to get YYYYMMDD HH:MM:SS you can do strftime("%Y%m%d %H:%M:%S", systime())

Upvotes: 1

Related Questions