From owner-freebsd-current@FreeBSD.ORG Wed Feb 2 13:59:27 2005 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 96A2516A4CE for ; Wed, 2 Feb 2005 13:59:27 +0000 (GMT) Received: from lurza.secnetix.de (lurza.secnetix.de [83.120.8.8]) by mx1.FreeBSD.org (Postfix) with ESMTP id A92DA43D2F for ; Wed, 2 Feb 2005 13:59:26 +0000 (GMT) (envelope-from olli@lurza.secnetix.de) Received: from lurza.secnetix.de (yjgxwf@localhost [127.0.0.1]) by lurza.secnetix.de (8.13.1/8.13.1) with ESMTP id j12DxOMH091659 for ; Wed, 2 Feb 2005 14:59:24 +0100 (CET) (envelope-from oliver.fromme@secnetix.de) Received: (from olli@localhost) by lurza.secnetix.de (8.13.1/8.13.1/Submit) id j12DxO1X091658; Wed, 2 Feb 2005 14:59:24 +0100 (CET) (envelope-from olli) Date: Wed, 2 Feb 2005 14:59:24 +0100 (CET) Message-Id: <200502021359.j12DxO1X091658@lurza.secnetix.de> From: Oliver Fromme To: freebsd-current@FreeBSD.ORG In-Reply-To: <20050201101113.J572@localhost> X-Newsgroups: list.freebsd-current User-Agent: tin/1.5.4-20000523 ("1959") (UNIX) (FreeBSD/4.11-RELEASE (i386)) MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Mailman-Approved-At: Wed, 02 Feb 2005 15:00:57 +0000 Subject: Re: cynchronised sleep capbilty.. X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Feb 2005 13:59:27 -0000 Julian Elischer wrote: > I often find myself wanting to write shell scripts that do: > > while : > do > {report some statistic} > sleep 10 > done > > > now this is of course only approximate as the delay will not be > exactly 10 seconds and it will gradually creep.. > > This doesn't matter too much except that I now need to do > the same on 50 machines and I need the data to line up. If a precision of 1 s is enough (i.e. the data will line up with a distance of no more than 1 s), the following will work fine: INTERVAL=10 # in seconds! while :; do NOW=`date +%s` sleep $(( ($NOW / $INTERVAL + 1 ) * $INTERVAL - $NOW )) report_results done It calls date(1) and sleep(1) once per 10 seconds, so the overhead is low. The following script snippet abuses sysctl kern.cp_time for subsecond precision (stathz is usually 128, so the precision is about 0.0078s). It calls sysctl(8), bc(1) and sleep(1) once per 10 seconds, so the overhead is still low. This one executes report_results exactly every 10 seconds, _but_ it's not synchronized when executed on multiple machines. To get both sub-second precision and synchronization to clocks across machines, an extension to sleep(1) would be required, as you suggested. I think it would also be nice to be able to get milliseconds from date(1), although that might be difficult to implement, because the strftime(3) interface isn't able to provide such information. Best regards Oliver INTERVAL=10 # in seconds! STATHZ=`sysctl -n kern.clockrate` STATHZ=${STATHZ%?} STATHZ=$(( ${STATHZ##*=} * `sysctl -n hw.ncpu` )) MOD=$(( $INTERVAL * $STATHZ )) StatCounter() { set -- `sysctl -n kern.cp_time` echo $(( $1 + $2 + $3 + $4 + $5 )) } while :; do TICKS=$(( $MOD - `StatCounter` % $MOD )) sleep `echo "scale=6; $TICKS / $STATHZ" | bc` report_results done -- Oliver Fromme, secnetix GmbH & Co KG, Oettingenstr. 2, 80538 München Any opinions expressed in this message may be personal to the author and may not necessarily reflect the opinions of secnetix in any way. "In My Egoistical Opinion, most people's C programs should be indented six feet downward and covered with dirt." -- Blair P. Houghton