2

As I was trying to execute a script in a new environment, I came up with this error:

[: 10: -lt: unexpected operator

Here is the painful part of the script:

end=$((SECONDS+60))
while [ $SECONDS -lt $end ];
do
   # process some queue...
   sleep 5
done

Origin system: Amazon Linux AMI release 2013.09 (cpe:/o:amazon:linux:2013.09:ga)

Destination system: Debian version 6.0.7

I can read that shell / bash / dash versions can vary, but this is still quite obscure to me. I tried to specify the correct shell on the first line of the script:

 #! /bin/bash

or

 #! /bin/sh

no chance...

I could also find out that users had similar error messages when using operator == instead of =. What would be the correct replacement for -lt then ? Is there any other solutions ? Any hint is warmly welcome !

3
  • 2
    Is $SECONDS actually set to a value? Oct 2, 2013 at 16:58
  • @MichaelHampton if I echo $SECONDS, I get a value that is increasing at a speed that reasonably looks like seconds. On both systems (though on one I get 1568..., and on the other 4511...).
    – mika
    Oct 2, 2013 at 17:08
  • @MichaelHampton It seems I did not call the echo in the correct way. See Dennis Williamson answer below for details :)
    – mika
    Oct 3, 2013 at 8:41

2 Answers 2

3

Dash doesn't support the $SECONDS auto-incrementing variable found in Bash. Because the variable has no value, the test command ([) sees an unset variable before the operator and produces the error you posted.

Demonstration:

$ dash -c 'echo "[$SECONDS]"'
[]
$ bash -c 'echo "[$SECONDS]"'
[0]
$ dash -c '[ $var -lt 3 ]'
dash: 1: [: -lt: unexpected operator
$ dash -c 'var=1; [ $var -lt 3 ]'
$

You can use the date command in order to do the check instead. Be aware that this could be expensive since you could call an external utility many times.

There may be other ways to accomplish what you're trying to do, but you don't say what that is.

Please also see BashFAQ/068.

3
  • About the context... I run this script every minute in the cron. This way, I get my task to run, and pause for 5 seconds, and run again... And stop launching agin after a minute. If the new script launched by cron overlaps the previous one, this is fine. Why doing this ? If my script crashes, I can make sure it starts again at most a minute later (with a new task, that will not crash). I agree there must be more elegant ways to achieve this. This is the script I've been using so far though, and it does the job, so... Thanks a lot for helping to fix it !
    – mika
    Oct 3, 2013 at 9:18
  • So using $(date '+%s') instead of SECONDS works well in this context. Since I wait between each loop, expensive external calls are not a worry :)
    – mika
    Oct 3, 2013 at 9:23
  • 1
    @mika: Please see Process Management (the section title refers to "game server" but the principle is more broadly applicable). Oct 3, 2013 at 12:29
0

Change the first line of the script to:

#!/bin/bash

If you are on Debian and (1) like bash and (2) know the script was written for a system that linked /bin/bash under /bin/sh. I gave up on trying to attempt universal /bin/sh scripts, it's a useless exercise if all the system under your control support bash.

I know it's an old question, but nobody gave the simplest answer.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .