Shell Script for Epoch Time Conversion

Hi there

I came across this script online to convert Epoch time to proper date format, but I am receiving the following error

Also, I have HISTTIMEFORMAT set in user's .profile so that their history output shows time stamps. Additionally I have changed their .history location to a dedicated directory in /var/log. Example as below:

export HISTFILE=/var/log/user_history/JP1_history

export HISTFILESIZE=20000

export HISTSIZE=5000

export HISTTIMEFORMAT="%F %T "

This is the error message from the script:

[root@H99A100 user_history]# ./test
Month '23' out of range 0..11 at -e line 2

This is the script I am using:

#!/bin/bash
# YYYY MM DD HH MM SS
# perl autosplits the string and uses timelocal to return
# the number of seconds from the Epoch
# No error checking!
function seconds_from_epoch {
echo $*| perl -MTime::Local -ane '
my $epochseconds = timelocal($F[5], $F[4], $F[3], $F[2], $F[1], $F[0]);
print "$epochseconds\n"; '
}

# parse file s32adm_bash_history date and time
set - $(ls -l s32adm_bash_history)
fdate=$6
ftime=$7

# parse the year, month, and day
set - $(IFS="-"; echo $fdate)
fyear=$1
fmonth=$2
fday=$3

# parse the hours and minutes
set - $(IFS=":"; echo $ftime)
fhour=$1
fmin=$2

totsecs=$(seconds_from_epoch "$fyear $fmonth $fday $fhour $fmin 0")
echo $totsecs

Can someone please point out what I am doing wrong?

echo $*

you are not passing any input arguments for your program.

Hi itkamaraj

I added echo $epochseconds| perl -MTime::Local -ane '

But i am getting this error now

[root@H99A100 user_history]# ./test
Day '' out of range 1..31 at -e line 2

@itkamaraj: $* is used in a function and it receives from the 2nd last line of the original script in post #1.

@hedkandi: Your original script in post #1 works for me without errors. Though, I didn't validate if the time in seconds from epoch is correct or not.

Couple of things that come to mind

  1. The parameters required for the perl timelocal function seem to be reversed (Time::Local - perldoc.perl.org)
  2. The timelocal function uses months 0-11 instead of 1-12
  3. Using ls -l like that is unreliable unless you control the format. Also, some ls switch to another format after 6 months and/or a year
  4. You need the echo $* because only one parameter gets past to the function instead of 6 (lose the double quotes around the parameters to make it 6)
  5. use set -- instead of set -

Hi Scrutinizer, thanks for your advise. I amended the script but its still not working

#!/bin/bash
# YYYY MM DD HH MM SS
# perl autosplits the string and uses timelocal to return
# the number of seconds from the Epoch
# No error checking!
function seconds_from_epoch {
echo $*| perl -MTime::Local -ane '
my $epochseconds = timegm($F[5], $F[4], $F[3], $F[2], $F[1], $F[0]);
print "$epochseconds\n"; '
}

# parse file s32adm_bash_history date and time
set -- $(ls -l s12adm_history)
fdate=$6
ftime=$7

# parse the year, month, and day
set -- $(IFS="-"; echo $fdate)
fyear=$0
fmonth=$1
fday=$2

# parse the hours and minutes
set -- $(IFS=":"; echo $ftime)
fhour=$3
fmin=$4
fsecs=$5

totsecs=$($fsecs $fmin $fhour $fday $fmonth $fyear)
echo $totsecs

I am getting this error now

[root@H99A100 user_history]# ./test
./test: line 29: Mar: command not found

Sorry, I'm not really good with scripts :frowning:

What is the output of ls -l s12adm_history ? It seems to me that "Mar" stands for "March", and the is hardly the input that you should feed into timegm or timelocal.

Hi Scrutinizer

This is my output

[root@H99 user_history]# ls -l s12adm_history
-rw-r--r-- 1 s12adm root 1890 Mar 27 12:23 s12adm_history

So if we look at this part of your script, we see that $fdate gets set to "Mar" and $ftime gets set to "27", which I don't think is as intended..

Hi Scrutinizer

I give up, I am using this one-liner added to cron that runs once a month at the end of each month and it worked. Only thing is that I have to set a cron for each users on the system

cat /var/log/user_history/nttd_jp1_history  | while read line ; do  if [[ $line =~ '^#' ]]; then  date -d "@$(echo $line | cut -c2-)
"; else echo $line ; fi; done