Re: Running a script every second
On Thu, Mar 06, 2014 at 02:34:25PM -0500, Michael Conrad wrote: > I know this borders on bike-shedding, but if you really want to run > something exactly 60 times per elapsed minute you need to compare > calls to clock_gettime(CLOCK_MONOTONIC). Nothing else will work > reliably in all cases, and certainly not signals. (if the system is > lagged significantly, two signals can be merged into one) POSIX timers with signal-based delivery can be used reliably for this purpose too. Realtime signals can be queued, and even if the queue overflows, the timer_getoverrun() function can tell you how many overruns there were (so you can compensate). In principle POSIX timers with thread-based delivery should also work for this purpose, but due to bugs in glibc, it's not 100% reliable and expirations may be lost. And if you don't mind using threads, it's easy to just roll your own approach with clock_gettime and clock_nanosleep with TIMER_ABSTIME, as you described. Rich ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: Running a script every second
Or, you could use a Xenomai-enabled Linux kernel. That way, Linux *is* realtime, so you will be guaranteed to get scheduled for execution every second. Mike Dean md...@emacinc.com http://www.emacinc.com/ Engineer EMAC, Inc. 618-529-4525 Ext. 330 618-457-0110 Fax 2390 EMAC Way Carbondale, Il 62901 On Thu, Mar 6, 2014 at 1:34 PM, Michael Conrad wrote: > I know this borders on bike-shedding, but if you really want to run > something exactly 60 times per elapsed minute you need to compare calls to > clock_gettime(CLOCK_MONOTONIC). Nothing else will work reliably in all > cases, and certainly not signals. (if the system is lagged significantly, > two signals can be merged into one) > > I'm not aware of any way to call clock_gettime from a shell script, but > Perl can do it. If you don't have perl and you still want it to be a > script for ease-of-maintenance, I would recommend: > > 1. write a very small C program that calls clock_gettime() for an > initial timestamp, writes "\n" on STDOUT, increment timestamp by exactly 1 > second, calls clock_gettime(), and then usleep()s for the difference > between clock_gettime and timestamp, if greater than 0. > > 2. write a script that performs "./c_prog | while read; do something(); > done" > > No special file descriptors, process IDs, signals or other mess, and > guaranteed one iteration of the script per every elapsed second (but no > guarantee that the execution occurs during that second. Linux isn't > realtime, afterall) > > -Mike > > > On 3/6/2014 9:25 AM, Yan Seiner wrote: > >> >> On 03/05/2014 10:49 PM, Harald Becker wrote: >> >>> Hi Yan ! >>> >>> On 05-03-2014 09:14 Yan Seiner wrote: >>> I am trying to run a script every second. >>> Beside what Laurent told about using sleep, etc. >>> >>> first script (the one that does the work) trap 'update' HUP mknod /tmp/dummyfifo p while true; do read < /tmp/dummyfifo > /dev/null 2>&1 done The problem is that the 'read' generates a /usr/bin/update: line 1: can't open /tmp/dummyfifo: Interrupted system call >>> The reason for this is you create your pipe once, but open it >>> again at every iteration of the loop. >>> >>> Try the following: >>> >>> mknod /tmp/dummyfifo p >>> exec 0/dev/null 2>&1 >>> while true; do >>> read >>> done >>> >>> This opens the fifo once and assigns it for stdin. After that it >>> stays open until the first script is terminated in any way. >>> >>> In addition stdout *AND* stderr are redirected to /dev/null for >>> all following commands in the script, so you need to redirect to >>> any file or tty when you want do display something. >>> >> >> Thanks! >> >> I like it. My solution leaves 'cat' processes behind if the script gets >> killed. Usually not a problem since it's only invoked at boot. >> >> ___ >> busybox mailing list >> busybox@busybox.net >> http://lists.busybox.net/mailman/listinfo/busybox >> > > ___ > busybox mailing list > busybox@busybox.net > http://lists.busybox.net/mailman/listinfo/busybox > ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: Running a script every second
I know this borders on bike-shedding, but if you really want to run something exactly 60 times per elapsed minute you need to compare calls to clock_gettime(CLOCK_MONOTONIC). Nothing else will work reliably in all cases, and certainly not signals. (if the system is lagged significantly, two signals can be merged into one) I'm not aware of any way to call clock_gettime from a shell script, but Perl can do it. If you don't have perl and you still want it to be a script for ease-of-maintenance, I would recommend: 1. write a very small C program that calls clock_gettime() for an initial timestamp, writes "\n" on STDOUT, increment timestamp by exactly 1 second, calls clock_gettime(), and then usleep()s for the difference between clock_gettime and timestamp, if greater than 0. 2. write a script that performs "./c_prog | while read; do something(); done" No special file descriptors, process IDs, signals or other mess, and guaranteed one iteration of the script per every elapsed second (but no guarantee that the execution occurs during that second. Linux isn't realtime, afterall) -Mike On 3/6/2014 9:25 AM, Yan Seiner wrote: On 03/05/2014 10:49 PM, Harald Becker wrote: Hi Yan ! On 05-03-2014 09:14 Yan Seiner wrote: I am trying to run a script every second. Beside what Laurent told about using sleep, etc. first script (the one that does the work) trap 'update' HUP mknod /tmp/dummyfifo p while true; do read < /tmp/dummyfifo > /dev/null 2>&1 done The problem is that the 'read' generates a /usr/bin/update: line 1: can't open /tmp/dummyfifo: Interrupted system call The reason for this is you create your pipe once, but open it again at every iteration of the loop. Try the following: mknod /tmp/dummyfifo p exec 0/dev/null 2>&1 while true; do read done This opens the fifo once and assigns it for stdin. After that it stays open until the first script is terminated in any way. In addition stdout *AND* stderr are redirected to /dev/null for all following commands in the script, so you need to redirect to any file or tty when you want do display something. Thanks! I like it. My solution leaves 'cat' processes behind if the script gets killed. Usually not a problem since it's only invoked at boot. ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
[PATCH 2/2] shuf: small usage text consistency fix
Signed-off-by: Bartosz Golaszewski --- coreutils/shuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coreutils/shuf.c b/coreutils/shuf.c index eff0d36..612b30e 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -17,13 +17,13 @@ //applet:IF_SHUF(APPLET_NOEXEC(shuf, shuf, BB_DIR_USR_BIN, BB_SUID_DROP, shuf)) //usage:#define shuf_trivial_usage -//usage: "[-e|-i LO-HI] [-n NUM] [-o FILE] [-z] [FILE|ARG...]" +//usage: "[-e|-i L-H] [-n NUM] [-o FILE] [-z] [FILE|ARG...]" //usage:#define shuf_full_usage "\n\n" //usage: "Write a random permutation of the input lines to standard output\n" //usage: "\n -e Treat each ARG as an input line" //usage: "\n -i L-H Treat each number L through H as an input line" //usage: "\n -n NUM Output at most NUM lines" -//usage: "\n -o Write result to FILE instead of standard output" +//usage: "\n -o FILE Write result to FILE instead of standard output" //usage: "\n -z End lines with zero byte, not newline" #include "libbb.h" -- 1.8.4.5 ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
[PATCH 1/2] shuf: fix a segfault on 'shuf -e'
Signed-off-by: Bartosz Golaszewski --- coreutils/shuf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/coreutils/shuf.c b/coreutils/shuf.c index f213d67..eff0d36 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -126,7 +126,9 @@ int shuf_main(int argc, char **argv) fclose_if_not_stdin(fp); } - shuffle_lines(lines, numlines); + /* Skip shuffle_lines() for one or zero lines. */ + if (numlines > 1) + shuffle_lines(lines, numlines); if (opts & OPT_o) xmove_fd(xopen(opt_o_str, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); -- 1.8.4.5 ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: Running a script every second
On 03/05/2014 10:49 PM, Harald Becker wrote: Hi Yan ! On 05-03-2014 09:14 Yan Seiner wrote: I am trying to run a script every second. Beside what Laurent told about using sleep, etc. first script (the one that does the work) trap 'update' HUP mknod /tmp/dummyfifo p while true; do read < /tmp/dummyfifo > /dev/null 2>&1 done The problem is that the 'read' generates a /usr/bin/update: line 1: can't open /tmp/dummyfifo: Interrupted system call The reason for this is you create your pipe once, but open it again at every iteration of the loop. Try the following: mknod /tmp/dummyfifo p exec 0/dev/null 2>&1 while true; do read done This opens the fifo once and assigns it for stdin. After that it stays open until the first script is terminated in any way. In addition stdout *AND* stderr are redirected to /dev/null for all following commands in the script, so you need to redirect to any file or tty when you want do display something. Thanks! I like it. My solution leaves 'cat' processes behind if the script gets killed. Usually not a problem since it's only invoked at boot. ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: Running a script every second
On 03/05/2014 10:07 AM, Laurent Bercot wrote: On 2014-03-05 17:40, Yan Seiner wrote: I am trying to run a script every second. I set up two scripts: Very dumb question: if your script execution time is much smaller than one second, why not simply "while true ; do update ; sleep 1 ; done" ? (Or better, "update ; exec sleep 1" in a runit/s6/... run script.) If your script execution time is not negligible compared to one second, you could replace "update" with "update &". If "update"'s execution time can go over one second, then you need to make it reentrant, but it's the same with your SIGHUP and fifo system. Given the constraints I have (which I left out of the original post) it's not a dumb question. 1. update has to run 60 times a minute. It's not critical that it run every second to the millisecond, but it does have to run 60 times a minute. A solution using "sleep" would not work since it takes a real and variable time to run update (between .2 and .5 seconds), and sleep is not guaranteed to take exactly 1 second. 2. update is stateful; it compares the state at its last execution with the current state. For that reason spawning update & will not work without a lot of overhead. 2.a) If I was to spawn it, I'd use watch -n 1 update and then I'd be done. 3. Overhead - I am working with a very limited board with low CPU power. Spawning a process every second adds about 2-3% cpu load. I went to fairly great lengths to build this script with shell builtins rather than spawning processes. I could (and probably will) rewrite this in C, but for now it's become an interesting exercise in shell scripting. And learning something is never dumb. This does, however, raise the question about watch - does it use sleep or does it actually trigger it every second? Time to look at code. ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox