Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I find myself frequently tasked with updating DNS records and needing to know exactly when the refresh will begin (a.k.a TTL expiration). I came up with this bash one-liner that gives me the output I want:

$ dig +noall +answer | \
> awk '{ print $2 }' | \
> { read secs; echo "`expr $secs / 60`m `expr $secs % 60`s remaining ($secs)"; }


3m 36s remaining (216)

I'd like to be able to wrap the watch command around this so that I can leave it running in a terminal and get a live countdown. Something like:

$ watch -n 10 "dig +noall +answer | \
> awk '{ print $2 }' | \
> { read secs; echo '`expr $secs / 60`m `expr $secs % 60`s remaining ($secs)'; }"

But this simply results in a non-functional watch instance followed by:

expr: syntax error

I am pretty sure this is some kind of piping/quoting problem and I'm not that well-versed on the intricacies. For the sake of portability I'd prefer to keep it as a one-liner vs. resorting to a script that requires saving to disk. Does anyone know the right way to accomplish this?

share|improve this question
up vote 1 down vote accepted

First of all you need to avoid using expr. It's rarely used. Instead I've here the version that does exact the same. Not much different than the above:

watch -n1 'dig +noall +answer | \ 
 awk "{print \$2}" | \
 { read secs; echo "$((secs / 60 ))m $((secs % 60))s remaining $((secs))";}'

Another aproach which can be used using tmux or screen

    while sleep 1; do dig +noall +answer | \ 
   { while read -r secs; do echo "$((secs / 60 ))m $((secs % 60))s remaining $((secs)) seconds"; done < <(awk '{print $2}' | \
   head -n1 ); };  done

Good luck.

share|improve this answer
Thank you so very much for this! (and to the others who posted answers). Works a treat! – luckman212 Jul 12 '13 at 17:11
The double parentheses around $secs at the end serve no purpose. – Dennis Williamson Jul 13 '13 at 4:20
@DennisWilliamson, Since arithmetic operations in bash happens within (()) and since $(()) evaluates an arithmetic operations, using $((secs)) isn't that weird. When it comes to $((secs)) of course we could have written it as in $secs. None would have heart in this case. $((secs)) is probably more a habit rather than style. – val0x00ff Jul 13 '13 at 12:06
time { a=345; for i in {0..1000000}; do echo "$((a))"; done > /dev/null; } is about 20% faster if you remove the parentheses. – Dennis Williamson Jul 13 '13 at 20:10

Why not let AWK do the math and printing?

watch -n 10 'dig +noall +answer | awk '\''{print int($2 / 60) "m", $2 % 60 "s remaining", "(" $2 ")"; exit}'\'''
share|improve this answer

The syntax error problem, because you forgot to escape the backstick character, the double quote character. And remember to escape dollar sign also, for the value of $secs is passed to expr, if you don't, there is no output to stdout:

watch -n 10 "dig +noall +answer | \
awk '{print\$2}' | \
{ read secs; echo \"\`expr \$secs / 60\`m \`expr \$secs % 60\`s remaining (\$secs)\"; }"
share|improve this answer

This seems to work for me.

watch -n 10 "dig +noall +answer | \
 awk '{print \$2}' | \
 { read secs; echo \"\$((\$secs / 60))m \$((\$secs % 60))s remaining\"; }"

or alternatively quoted to avoid quite that much mess:

watch -n 1 'dig +noall +answer | \
 awk "{print \$2}" | \
 { read secs; echo "$(($secs / 60))m $(($secs % 60))s remaining"; }'
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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