8

I want to start the w command periodically, according to man watch the smallest possible time interval is 0.1.

I tried:

watch -n1 w        (works)
watch -n1.5 w      (does not work)
watch -n0.1 w      (does not work)

When I try to start the watch command with the n-option as non-integer, I get the error message:

watch: failed to parse argument: '0.1'
roaima
  • 107,089
  • 14
  • 139
  • 261
Abdul Al Hazred
  • 25,760
  • 23
  • 64
  • 88

3 Answers3

17

This is a locale problem. watch uses strtod(3), which is locale-dependent, to convert the argument to -n to a double.

To fix the problem, you need to either specify the argument to -n with a different separator:

watch -n 0,1 w

Or change your locale to a setting where the period character is used for the decimal point:

export LC_NUMERIC=en_US.UTF-8
watch -n 0.1 w


A couple of references:

  1. A relevant portion of the Linux manpage for strtod:

A decimal number consists of a nonempty sequence of decimal digits possibly containing a radix character (decimal point, locale-dependent, usually '.')

  1. You can review your current settings by running locale in your terminal:

    locale
    LANG=en_US.UTF-8
    LC_CTYPE="en_US.UTF-8"
    LC_NUMERIC="en_US.UTF-8"
    LC_TIME="en_US.UTF-8"
    LC_COLLATE="en_US.UTF-8"
    LC_MONETARY="en_US.UTF-8"
    ...
    
  2. The source code in question can be reviewed at gitlab:

    https://gitlab.com/procps-ng/procps/blob/85fff468fa263cdd2ff1c0144579527c32333695/watch.c#L625

    https://gitlab.com/procps-ng/procps/blob/85fff468fa263cdd2ff1c0144579527c32333695/lib/strutils.c#L49

(edit 2017-09-07): updated gitlab links

zackse
  • 1,513
  • 9
  • 10
3

Just a complement to zackse's fine answer.

There are two problems with:

LC_NUMERIC=en_US.UTF-8 watch -n 0.1 w

as a work around for the fact that watch expect numbers formatted in the user's convention while you expect it to be in the English format.

  1. That doesn't work if LC_ALL is set. LC_ALL overrides all other locale settings including LC_NUMERIC. The work around would be to use:

    LC_ALL=en_US.UTF-8 watch -n 0.1 w
    

    but then it would make the second point below even worse

  2. the command started by watch (in this case w) inherits that LC_NUMERIC. So instead of outputting its numbers in a format expected by the user, it will output it in the US English format.

Ideally here, we'd want to tell watch to run w every tenth of a second (regardless of the user's locale) without affecting the behaviour of the w command (which should always give an output understandable by the user in his own locale).

With the yash shell, you can do it with:

 watch -n "$((0.1))" w

yash is one of the 3 Bourne-like shells that support floating point arithmetics (the other ones being zsh and ksh93). It's the only one that does internationalisation properly though. zsh always uses . as the decimal mark, and ksh93 honours the one from the locale event in its internal syntax.

For yash, . is the decimal mark for its arithmetic syntax, but it honours the locale's one upon input/output.

Another trick you can use here is to avoid inputting the decimal mark altogether by using scientific notation:

watch -n 1e-1 w

Or you can query the decimal mark from the locale:

m=$(locale decimal_point)
watch -n "0${m}1" w
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
0

The commands watch and w have nothing to do with each other other than the first letter being equal. You cannot assume that a parameter for w is equally valid for watch. The watch command takes an integral number of seconds as the value for -n.

Incidentally, I've also looked at the man page for w and I can't see any reference to a time period. I'm curious to know from where you got this information so that I can (hopefully) explain further.

UPDATE

It appears that you are actually referring to the timer for watch, not for w. I will update your question to match this new disclosure. Having finally discovered this, I cannot see anything wrong with watch -n 0.1 w.

roaima
  • 107,089
  • 14
  • 139
  • 261
  • I am now somehow confused, because all I know is that the watch-command executes periodically another command, regardless whether this command has a remark about usage of time in its man. I thought "watch " is true for all commands without exceptions, like even "watch ls" though this one makes no sense it shows no error in the shell either. – Abdul Al Hazred Mar 29 '15 at 18:25
  • @AbdulAlHazred you are correct in that `watch` periodically executes another command. What I don't understand is why you think that the parameters for `w` should apply to `watch`. The command `watch ls` runs the `ls` command every two seconds, updating your screen with its current output. – roaima Mar 29 '15 at 20:19
  • I was told, that in the column idle of this commands output I can read for how long the keyboard has not been pressed. so I fought if i start "watch w" i could watch the time increasing and then after pressing a key the time would drop to zero. i tried first just with one terminal and the idle time increased further even after pressing a key, second time i opened additionally a further terminal and when i pressed a key the idle time indeed changed, but not in a way as i espected, so i fought maybe it is a delay-effect that is why i wanted to test watch with a very short time interval. – Abdul Al Hazred Mar 29 '15 at 20:55
  • @AbdulAlHazred `watch` uses integer second intervals. If I run `watch -d -n1 w` in one terminal and type keys on the keyboard in another I can see the _idle time_ dropping back down each time I type something. – roaima Mar 29 '15 at 21:24
  • me too, but what i do not get is , that when i press the key the time does not drop to 0 , it sometimes only goes a few seconds back, say from 20 to 17, and when it goes further back when i press several times in continuation a key. i thought it would be simply: one keypress = back to 0, but it is not like this, it has some strange logic how to go back of its own. – Abdul Al Hazred Mar 29 '15 at 21:32
  • I still do not understand it when I compare it with the text in the man page of watch: -n, --interval seconds Specify update interval. The command will not allow quicker than 0.1 second interval, in which the smaller values are con‐ verted. ...........also in another question someone posts an non integer value for watch -n . – Abdul Al Hazred Mar 29 '15 at 22:10
  • @AbdulAlHazred you said this time was in the man page for `w`. Not for `watch`. – roaima Mar 29 '15 at 22:42