Operating System - Linux
1753618 Members
5825 Online
108797 Solutions
New Discussion юеВ

Re: HP-UX shell or OE access to epoch secs

 
SOLVED
Go to solution
Ralph Grothe
Honored Contributor

HP-UX shell or OE access to epoch secs

Hello,

the GNU date command offers among many other useful extensions the %s flag that provides epoch seconds.
I have several shell scripts to be run on hpux that require them and make a fork to Perl to whenever they need to fetch them.
But I always feel that the whole script should better be written in Perl anew whenever I have more than 3 awk or 1 Perl calls in it.
I wonder if maybe HP have hidden somewhere a shell call (or env var similar to $SECONDS) to get them more "directly"?


$ uname -sr; rpm -qf $(which date); date +%s; perl -le print\ time
Linux 2.6.9-1.667smp
coreutils-5.2.1-31
1155020000
1155020000
Madness, thy name is system administration
12 REPLIES 12
Peter Nikitka
Honored Contributor

Re: HP-UX shell or OE access to epoch secs

Hi,

while changing a (shell)-script implementation to perl is a good idea in general, it clearly depends on the length and structure of the task of the script and the amount of time availble to port it.

Take a look at your script and analyze what commands are called which are not builtins:
If there are few the 'perlification' should be (enough perl knowhow granted) easy.
If there are many external command calls, the benefit of changing
a=$(command1)
to
open (FD,"command|");
while()..
will be close to zero.

If your are in a phase of porting a script to other UNIXes or even to WIN$, that approach should be really considered.
Just for the sake of eliminating a few system() calls it is mostly an oversized effort.

mfG Peter

PS: I don't know of any 'hidden' calls or option to one in HP-UX as a substitute for
perl -le 'print time;' .
The Universe is a pretty big place, it's bigger than anything anyone has ever dreamed of before. So if it's just us, seems like an awful waste of space, right? Jodie Foster in "Contact"
James R. Ferguson
Acclaimed Contributor

Re: HP-UX shell or OE access to epoch secs

Hi Ralph:

I agree with Peter's comments. Depending upon the number and number of times a script has to fork 'awk', 'sed', 'perl' or for that matter any external command, can often be reduced, improving the overall efficiency of the code.

I have seen too many shell scripts use 'cat' to read a file only to pipe the output to 'sed' or 'awk'. A collorary is using 'cat' to pipe into a shell 'while read...' instead of redirecting the input inline. Other overhead occurs when a pipeline of 'grep' output is passed to 'awk' only to print a field or two.

I too, don't know of any direct way to get the epoch seconds other than calling a perl snippet.

Regards!

...JRF...
A. Clay Stephenson
Acclaimed Contributor
Solution

Re: HP-UX shell or OE access to epoch secs

A variation on your theme would be to call Perl once to get the epoch seconds in ${EPOCH0} and then immediately store the shell variable $SECONDS as something like ${SECONDS0}. All your subsequent values would then be and no additional external calls would be needed:

EPOCHNOW=$((${SECONDS} - ${SECONDS0} + ${EPOCH0}))

It would be rather easy to create a function which was smart enough to call Perl if ${EPOCH0} were not set and to set ${SECONDS0} at the same time so that all of your script's actual use of the seconds would be to simply call this function.

If it ain't broke, I can fix that.
Ralph Grothe
Honored Contributor

Re: HP-UX shell or OE access to epoch secs

Clay,

nice workaround.
I have to revisit man sh-posix to find out if typeset -i can perform these "bigint" arithmetics.
Madness, thy name is system administration
A. Clay Stephenson
Acclaimed Contributor

Re: HP-UX shell or OE access to epoch secs

Epoch seconds won't overflow 32-bit signed integers until 2038 so it's as safe as most current UNIX'es. I've done thunk'ed about this some more and here is a pure shell equivalent that borrowed a function from another script.
--------------------------------------------
#!/usr/bin/sh

cal_jdate() # expects 3 args: month, day, year; outputs truncated Julian Day
{
typeset -i MO=${1}
typeset -i DA=${2}
typeset -i YR=${3}
shift 3
typeset -i JD=0
JD=$((${DA} - 32075 + (1461 * (${YR} + 4800 + ((${MO} - 14)/12)) / 4) + \
((367 * (${MO} - 2 - ((${MO} - 14)/12) * 12))/12) - \
((3 * ((${YR} + 4900 + ((${MO} - 14)/12))/100))/4)))
echo "${JD}"
return 0
} # cal_jdate

epoch()
{
typeset -i MON=0
typeset -i DAY=0
typeset -i YEAR=0
typeset -i HOUR=0
typeset -i MIN=0
typeset -i SEC=0
typeset -i JD1970=2440588 # Julian Day of 1-Jan-1970
date -u '+%m %d %Y %H %M %S' | read MON DAY YEAR HOUR MIN SEC
typeset -i JD=$(( $(cal_jdate ${MON} ${DAY} ${YEAR}) - ${JD1970} ))
typeset -i EP=$(((${JD} * 86400) + (${HOUR} * 3600) + (${MIN} * 60) + ${SEC}))
echo "${EP}"
return 0
} # epoch


typeset -i NOW=$(epoch)
echo "Epoch Seconds = ${NOW}"

perl -e 'print "From Perl: ",time(),"\n"'
-------------------------------------------

Note that I call Perl immediately afterwards to make sure that they agree though obviously your production version would get rid of that perl line. This version too won't explode until 2038 (unless UNIX is fixed).

This approach should work on all flavors of UNIX although on Linux I generally use zsh rather than bash because many versions of bash have problems with this construct:

echo "One Two Three" | read A B C
echo "A=${A}"
echo "B=${B}"
echo "C=${C}"
If it ain't broke, I can fix that.
A. Clay Stephenson
Acclaimed Contributor

Re: HP-UX shell or OE access to epoch secs

... and here is a little better implementation combining my 1st and 2nd ideas so that while it is a pure shell solution only calls the external date command once and caches the initial vales and then leverages $SECONDS for subsequent calls:

-----------------------------------------
#!/usr/bin/sh

# 08/08/2006 acs pure shell epoch seconds routine; caches data so that
# date -u only needs to be called once but does depend upon
# the ksh (and POSIX) built-in variable SECONDS
#

cal_jdate() # expects 3 args: month, day, year; outputs truncated Julian Day
{
typeset -i MO=${1}
typeset -i DA=${2}
typeset -i YR=${3}
shift 3
typeset -i JD=0
JD=$((${DA} - 32075 + (1461 * (${YR} + 4800 + ((${MO} - 14)/12)) / 4) + \
((367 * (${MO} - 2 - ((${MO} - 14)/12) * 12))/12) - \
((3 * ((${YR} + 4900 + ((${MO} - 14)/12))/100))/4)))
echo "${JD}"
return 0
} # cal_jdate

typeset -i EPOCH=-1
typeset -i SECONDS0=-1

epoch()
{
typeset -i EP=0
if [[ ${EPOCH} -gt 0 ]]
then
EP=$((${SECONDS} - ${SECONDS0} + ${EPOCH}))
else
typeset -i MON=0
typeset -i DAY=0
typeset -i YEAR=0
typeset -i HOUR=0
typeset -i MIN=0
typeset -i SEC=0
typeset -i JD1970=2440588 # Julian Day of 1-Jan-1970
date -u '+%m %d %Y %H %M %S' | read MON DAY YEAR HOUR MIN SEC
typeset -i JD=$(( $(cal_jdate ${MON} ${DAY} ${YEAR}) - ${JD1970} ))
EP=$(((${JD} * 86400) + (${HOUR} * 3600) + (${MIN} * 60) + ${SEC}))
SECONDS0=${SECONDS}
EPOCH=${EP}
fi
echo "${EP}"
return 0
} # epoch


typeset -i NOW=$(epoch)
echo "Epoch Seconds = ${NOW}"
perl -e 'print "From Perl: ",time(),"\n"'
echo "Sleeping 10 seconds"
sleep 10
NOW=$(epoch)
echo "Epoch Seconds = ${NOW}"
perl -e 'print "From Perl: ",time(),"\n"'


If it ain't broke, I can fix that.
A. Clay Stephenson
Acclaimed Contributor

Re: HP-UX shell or OE access to epoch secs

and an even slighty better version in that ${SECONDS0} is really not needed because ${SECONDS} can be subtracted one time for the current epoch seconds and cache that value.
-------------------------------------------

#!/usr/bin/sh

# 08/08/2006 acs pure shell epoch seconds routine; caches data so that
# date -u need be called but once; requires that the shell
# implement the built-in variable SECONDS

cal_jdate() # expects 3 args: month, day, year; outputs truncated Julian Day
{
typeset -i MO=${1}
typeset -i DA=${2}
typeset -i YR=${3}
shift 3
typeset -i JD=0
JD=$((${DA} - 32075 + (1461 * (${YR} + 4800 + ((${MO} - 14)/12)) / 4) + \
((367 * (${MO} - 2 - ((${MO} - 14)/12) * 12))/12) - \
((3 * ((${YR} + 4900 + ((${MO} - 14)/12))/100))/4)))
echo "${JD}"
return 0
} # cal_jdate

typeset -i EPOCH=-1

epoch()
{
typeset -i EP=0
if [[ ${EPOCH} -gt 0 ]]
then
EP=$((${SECONDS} + ${EPOCH}))
else
typeset -i MON=0
typeset -i DAY=0
typeset -i YEAR=0
typeset -i HOUR=0
typeset -i MIN=0
typeset -i SEC=0
typeset -i JD1970=2440588 # Julian Day of 1-Jan-1970
date -u '+%m %d %Y %H %M %S' | read MON DAY YEAR HOUR MIN SEC
typeset -i JD=$(( $(cal_jdate ${MON} ${DAY} ${YEAR}) - ${JD1970} ))
EP=$(((${JD} * 86400) + (${HOUR} * 3600) + (${MIN} * 60) + ${SEC}))
EPOCH=$((${EP} - ${SECONDS}))
fi
echo "${EP}"
return 0
} # epoch


typeset -i NOW=$(epoch)
echo "Epoch Seconds = ${NOW}"
perl -e 'print "From Perl: ",time(),"\n"'
echo "Sleeping 10 seconds"
sleep 10
NOW=$(epoch)
echo "Epoch Seconds = ${NOW}"
perl -e 'print "From Perl: ",time(),"\n"'

If it ain't broke, I can fix that.
Sandman!
Honored Contributor

Re: HP-UX shell or OE access to epoch secs

How about creating your own executable and use it in place of date whenever you need to get the seconds since the Unix epoch...since the program needs minimal coding and can be placed and invoked from the /usr/local/bin directory.

#include
#include

main(int argc, char *argv[])
{
time_t tloc, *ptloc = &tloc;
printf("seconds since epoch: %ld\n", time(ptloc));
}

...compile and execute as

# cc -o epochsecs epochsecs.c
# /usr/local/bin/epochsecs
A. Clay Stephenson
Acclaimed Contributor

Re: HP-UX shell or OE access to epoch secs

The whole point is to avoid exec's and the use of non-standard commands. Coding a small c program is no different that simply perl -e 'print time'.
If it ain't broke, I can fix that.