2

I want to increment a variable by one every 3 seconds. Is there any way to do that using bash?

I had a program running in infinite loop in which I am doing some stuff with a variable; I want to increment that variable, say, every 3 seconds, I am not supposed to use sleep.

  • Do you need to do this asynchronously, i.e. while other things happens, without, say, sleeping for three seconds? – Kusalananda Sep 16 at 14:53
  • Yeah, I can't use sleep – charan priyatham Sep 16 at 14:54
3

In bash, the $SECONDS special variable is already incremented once every second like in ksh where the feature comes from.

It's initialised to 0 at the time the shell starts (or from the value of the $SECONDS environment variable if it's there), but you can also set its value by hand.

However note that bash's implementation (contrary to that of ksh93, mksh or zsh, the latter two used to have the same bug but it was fixed after I reported it) is broken in that it is incremented when the system clock passes an exact second mark.

So, if you set it to 0 at 12:00:00.1 or 12:00:00.9 it will change to 1 at 12:00:01 (so 9/10 second later in the first case and 1/10 second later in the second)

You may want to switch to zsh, mksh or ksh93 instead.

And then you just need to use $((SECONDS*3)) for something that is incremented by 3 every second or $((SECONDS/3)) for something that is incremented by 1 every 3 seconds.

In ksh93, you could define the get discipline of an arbitrary variable as $((SECONDS*3)):

#! /bin/ksh93 -
var.get() {
  .sh.value=$((int(SECONDS*3)))
}
SECONDS=0

# testing:
echo "$var"; sleep 1; echo "$var"

gives:

0
3

Still in ksh93, you could define a type of variable that gets incremented by any arbitrary number every seconds with something like:

#! /bin/ksh93 -
SECONDS=0
typeset -T auto_incremented=(
  typeset -F start
  typeset -i initial=0
  typeset -i increment=1
  function get {
    .sh.value=$((_.initial + int((SECONDS - _.start) * _.increment)))
  }
  function create {
    ((_.start = SECONDS))
  }
  function set {
    _.initial=${.sh.value}
    ((_.start = SECONDS))
  }
)

# testing:
auto_incremented var
var.increment=2

echo "$var"; sleep 2; echo "$var"

var=10; echo "$var"; sleep 2; echo "$var"

Which here gives:

0
4
10
14

Though bash copied quite a few features from ksh, it didn't copy disciplines, types or a floating point $SECONDS.

In bash, one approach you could take is run some background process that sends a signal every second to bash and install a trap on that signal that updates the variable, like:

#! /bin/bash -
var=0 SECONDS=0; trap '((var = SECONDS * 3))' ALRM

ksh93 -c '
  t=0 SECONDS=0
  while
    sleep "$((++t - SECONDS))" && kill -s ALRM -- "$1" 2> /dev/null
  do
    : nothing
  done' ksh "$$" &

# testing:
echo "$var"; sleep 2; echo "$var"

Note that we can't just increment $var in the trap handler as traps are only processed in-between non-builtin commands and if one of those commands take more than 1 second, during which more than one SIGALRM signal is sent, only one will be processed.

Here we're using a ksh93 inline script to do the signal sending every second, but you could use zsh, perl, python... instead if available.

0

A horrible solution:

#!/bin/bash
somevar=0
somefile=$(mktemp)
echo "$somevar" > "$somefile"
while true; do sleep 3; ((somevar++)); echo "$somevar" > "$somefile" ;done &

  while true; do

    sleep 1
    avar="$(cat "$somefile")"
    echo "my var has value $avar"

  done

Certainly NOT precise with the times and NOWHERE near realtime-ready...

-1

Below is code

 i=10
    for ((j=1;j<=count_of_sequence;j++)); do echo $i; sleep 10;i=$(($i+1)); done

output

10
11
12
13
14
  • 1
    This is unfortunately exactly what the user does not want to do. They want their variable to be updated every three seconds while doing other things (not while sleeping). – Kusalananda Sep 17 at 8:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.