I am trying to write a script that will accomplish the following:
query current system time and store result into a variable
wait for some amount of time, say 300 seconds
reset system time to earlier queried time + 1 second
I did some basic shell scripting (CSH mainly) and took an intro to perl class in 2000 but have not touched either since, and as a result I really have no idea how to accomplish this task. I'm also not really sure how to do the math on the time since the systemsetup -settime requires hh:mm:ss, so at 59 seconds I'll run into a problem
I'm currently using OS X 10.6.6 and /bin says I have access to bash, csh, ksh, tcsh, and zsh. I have no preference for which shell the script runs in, although echo $SHELL says my current default is bash, if that makes any difference.
I would also like to use argv (or something similar) to define how many cycles I'd like to process to repeat and possibly to define the wait time as well instead of hard coding these into the script.
KevinGB is on the right track - the script isn't meant to adjust the system time to a reference time source to keep it accurate. I have an application that references the system time and I want to run that application for a set period of time, from say 12:00:00 to 12:05:00, tabulate the output, and then reset the system clock to 12:00:01 and run the application from 12:00:01 to 12:05:01 and compare the output to the previous run.
Actually, since I originally posted I realized that I don't need to query the current time at all. Instead I can just pass a clock time, wait period (in seconds), next cycle increment (in seconds), and an exit time into the script. This should get me around quite a number of the problems I was initially having and will hopefully simply the script down to something I can muddle my way through. Anyhow, I could do something like:
> script 12:00:00 300 1 12:00:05
which would hopefully:
set the system time to 12:00:00
wait for n seconds
increment the input system time by increment (in this case 1 second)
compare the result to the end time (passed in from script) and if new system time is less end time
reset system time and loop to wait for n seconds
so in this scenario I should get 5 cycles that lasted for 5 minutes each and my timestamp on the data that is being collected would show:
It is not advisible to change the system time in the manner proposed in post #1. Hard setting the date/time should only be done in single user mode armed with full knowledge of the effects on programs such as System Accounting and any Database Engines you may have.
What are you trying to do? We seem to have a proposed solution without knowing the problem.
If your system clock is a little bit fast, there should be a clock drift function (see "man date"). Or if you have access to a Time Server, use NTP as ctsgnb advises.
(Post drafted before seeing post #4). There has to be a better way which does not involve messing with the system clock.
This is a single user stand alone system running a custom simulation application for which I am collecting results at 1 second intervals. The application takes into account the time of day, which it gets from the system time. IE my data output from 12:00:00 - 12:59:59 will be different than the data output from 13:00:00 - 13:59:59, even though I have not changed any of the application parameters.
Since I can't change the behavior of the application (it getting it's simulation time from the system clock) I have been running the application for a set period of time and then re-adjusting the system clock by hand. I'm looking for a way to let the application run continuously, but appear as if it had been run for a set number of cycles with each cycle lasting a set period of time, and each cycle beginning from an incremental offset.
Hope that helps clarify the problem I'm trying to solve with the script.
Be careful. As you appear to be only changing the time (not the date) there is likely to be less impact. The unix "date" command will accept just a time parameter. Be aware of post-dated files.
During Y2K testing I had to set up a "Groundhog Day" system which repeated the same given day again-and-again and needed to save and reset (or replace) system accounting files, system logs, software licence files etc. etc. and deal with timestamps on post-dated files (or remove them as appropriate). This was not trivial.
One awful database crash I attended was caused by someone changing the system clock by a couple of minutes.
So I've been making some progress on my question and I was actually playing around with the date command before I saw your response. On mac OS I have been using the command:
systemsetup -gettime which returns Time: HH:MM:SS
so I've been trying to figure out how to strip Time: and assign hours=HH minutes=MM seconds=SS. I could then:
sh script.sh 300 1 10
get current system time with systemsetup -gettime
strip Time: and convert the system time to seconds
initialize cycle count to 1 and
while count less than 10 (passed in from command line as $3) do
wait for 300 seconds (passed in from command line as $1)
add the increment 1 (passed in from command line as $2) to system time converted to seconds as new_systemtime
convert new_systemtime back to HH:MM:SS format
reset system time to new_systemtime by systemsetup -settime $new_systemtime
increment cycle_count by 1
I was able to use awk -F: to print each number independently. It's ugly, but:
but then I got stuck at how to shove $2 $3 and $4 into the variables hours, minutes, and seconds instead of printing them.
Anyhow, any tips would be greatly appreciated on how to go about each of those steps, or if I'm just going about it all the wrong way, that'd be good to know too
Maybe try saving the current time in a file in a private directory with the name of the file the value of HHMMSS . Then (after 300 seconds or whatever) use the name of the file in a unix "date" command to reset the time as required.
When working with Groundhog Day software testing the advantage of using a file instead of a Shell environment variable is that it survives system reboots. Also, you can alter the name of the file to whatever you want.
So I fumbled through it and I've managed to get my script running, all except re-setting the system time. I have $h $m $s and I'm trying to make a single variable $set_time that takes the form $h:$m:$s. Everything I've tried I just end up with $h $m $s. How do I get a colon included in the variable?
Thanks! Here's the whole thing, in case it helps.
# Call this script with parameters for wait_time, increment, and cycle_count
#
# example sh test.sh 300 1 10
# this will sleep for 300 seconds, increment the start time by 1 second, and run
# for 10 cycles
# Saving variables passed in from command line for later use
wait_time=$1
echo "Wait time in seconds: "$wait_time
increment=$2
echo "Increment in seconds: "$increment
cycle_count=$3
echo "Itteration cycles: "$cycle_count
# Turning network clock off
systemsetup -setusingnetworktime off
# getting on with it
read -p "Hit any key when ready to begin"
init_time=$(systemsetup -gettime)
echo "Reference time will be set as: "$init_time
# converting current system time to seconds
d=$init_time
IFS=":"
set -- $d
hr=$2
min=$3
sec=$4
# strip leading white space from hr
hr=$(echo $hr | tr -d " ")
# echo "IFS time in seconds: $(((hr*3600)+(min*60)+sec))"
ref_time=$(((hr*3600)+(min*60)+sec))
# echo "\$ref_time set to: "$ref_time
#inserting while loop
COUNTER=0
while [ $COUNTER -lt $cycle_count ]; do
echo Cycle count: $COUNTER
echo "sleeping for $wait_time seconds"
# Don't want to sleep while testing
# sleep $wait_time
# Adding $increment to $ref_time
new_time=$((ref_time+increment))
# echo "old ref_time was: "$ref_time
ref_time=$new_time
# echo "new ref_time is: "$new_time
# Converting new_time to HH:MM:SS for set_time
secs=$new_time
# echo "\$secs set to: "$new_time
h=$(( secs / 3600 ))
m=$(( ( secs / 60 ) % 60 ))
s=$(( secs % 60 ))
echo "system time will be sets as: systemsetup -settime $h":"$m":"$s"
set_time=$h:$m:$s
echo $set_time
# systemsetup -settime $h":"$m":"$s"
let COUNTER=COUNTER+1
done
# Turning network clock on
systemsetup -setusingnetworktime on
---------- Post updated at 02:51 PM ---------- Previous update was at 02:32 PM ----------
Bugger!
I found the problem. line 25
IFS=":"
So I added
IFS=":"
set -- $d
hr=$2
min=$3
sec=$4
# Adding this as a wild hair, what if IFS above is causing problems?
IFS=";"
I have never used IFS, but I suspect that I should unset it, rather than setting to a semi-colon to solve the problem.