[GRASS-dev] [bug #5499] (grass) bash scripts starting with #!/bin/sh

this bug's URL: http://intevation.de/rt/webrt?serial_num=5499
-------------------------------------------------------------------------

Subject: bash scripts starting with #!/bin/sh

Platform: GNU/Linux/x86
grass obtained from: Other (CDROM etc)
grass binary for platform: Downloaded precompiled Binaries
GRASS Version: 6.2.1

I experienced problems with Ubuntu 6.10 installation. The r.in.wms script refused to work with errors like this:
/usr/lib/grass/etc/r.in.wms//wms.request: 326: SIZE_ARRAY[0]=: not found
/usr/lib/grass/scripts/r.tileset: 193: declare: not found
/usr/lib/grass/scripts/r.tileset: 258: Syntax error: Bad for loop variable

It took me about a couple of hours to find out that the reason is that Ubuntu developers decided to change the symbolic link /bin/sh from /bin/bash to /bin/dash, which is POSIX-compliant, but much less feature-rich than bash.

Setting it back to /bin/bash solved the problem, but still indicating the right interpreter in the headers will also be great.

-------------------------------------------- Managed by Request Tracker

Request Tracker wrote:

this bug's URL: http://intevation.de/rt/webrt?serial_num=5499
-------------------------------------------------------------------------

Subject: bash scripts starting with #!/bin/sh

Platform: GNU/Linux/x86
grass obtained from: Other (CDROM etc)
grass binary for platform: Downloaded precompiled Binaries
GRASS Version: 6.2.1

I experienced problems with Ubuntu 6.10 installation. The r.in.wms script refused to work with errors like this:
/usr/lib/grass/etc/r.in.wms//wms.request: 326: SIZE_ARRAY[0]=: not found
/usr/lib/grass/scripts/r.tileset: 193: declare: not found
/usr/lib/grass/scripts/r.tileset: 258: Syntax error: Bad for loop variable

It took me about a couple of hours to find out that the reason is that
Ubuntu developers decided to change the symbolic link /bin/sh from
/bin/bash to /bin/dash, which is POSIX-compliant, but much less
feature-rich than bash.

Setting it back to /bin/bash solved the problem, but still indicating
the right interpreter in the headers will also be great.

The problem is that you can't rely upon bash being installed in a
specific location[1]. On Linux, it's the "primary" shell, so it's
/bin. On Unices which include it as an "extra", it's likely to be in
/usr/bin. If it isn't part of the core OS, it could be anywhere,
although /usr/local/bin, /sw/bin and /opt/sw/bin are all plausible.

[1] Actually, you can't rely upon bash being installed at all. GRASS
isn't specifically a Linux package; at least, it isn't supposed to be.

The only thing which you can absolutely rely upon is that /bin/sh will
be a POSIX-compatible Bourne shell. Anyone writing scripts would do
well to bear this in mind (IOW, please avoid using bash-specific
features).

--
Glynn Clements <glynn@gclements.plus.com>

> I experienced problems with Ubuntu 6.10 installation. The r.in.wms
> script refused to work with errors like this:
> /usr/lib/grass/etc/r.in.wms//wms.request: 326: SIZE_ARRAY[0]=: not
> found

The broken PROJ_UNITS parsing in r.tileset is fixed in 6.3 CVS and
backported to the 6.2.x branch.

The bash vs. ash issue in r.in.wms is not fixed.

is this valid Bourne sh or is it a Bash extension?

SIZE_ARRAY[0]=""

this link indicates that they are Bash only:
  http://tldp.org/LDP/abs/html/arrays.html

more on arrays (concept is new to me)
  http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html

Hamish

Hamish wrote:

> > I experienced problems with Ubuntu 6.10 installation. The r.in.wms
> > script refused to work with errors like this:
> > /usr/lib/grass/etc/r.in.wms//wms.request: 326: SIZE_ARRAY[0]=: not
> > found

The broken PROJ_UNITS parsing in r.tileset is fixed in 6.3 CVS and
backported to the 6.2.x branch.

The bash vs. ash issue in r.in.wms is not fixed.

is this valid Bourne sh or is it a Bash extension?

SIZE_ARRAY[0]=""

Arrays are a bash extension.

AFAICT, the array is never actually used, so removing that line should
be harmless.

--
Glynn Clements <glynn@gclements.plus.com>

Glynn Clements wrote:

[r.in.wms/wms.request]

Arrays are a bash extension.

AFAICT, the array is never actually used, so removing that line should
be harmless.

done in CVS, along with some other cleanups. r.in.wms still needs a lot
more error checking built into it*, but is now free of bashisms.

[*] it now exits gracefully if r.tileset (by way of wms.request) failed.

[r.tileset]

> Setting it back to /bin/bash solved the problem, but still
> indicating the right interpreter in the headers will also be great.

Glynn:

The problem is that you can't rely upon bash being installed in a
specific location[1]. On Linux, it's the "primary" shell, so it's
/bin. On Unices which include it as an "extra", it's likely to be in
/usr/bin. If it isn't part of the core OS, it could be anywhere,
although /usr/local/bin, /sw/bin and /opt/sw/bin are all plausible.

[1] Actually, you can't rely upon bash being installed at all. GRASS
isn't specifically a Linux package; at least, it isn't supposed to be.

The only thing which you can absolutely rely upon is that /bin/sh will
be a POSIX-compatible Bourne shell. Anyone writing scripts would do
well to bear this in mind (IOW, please avoid using bash-specific
features).

I don't think it is practical for r.tileset to be free of Bash without
a complete rewrite. It's really a Bash program and not a shell script.

If it were to be rewritten, perhaps do it in python, but as bash will
be more widely installed than python I see little point in doing that.
Python (or perl) will have the same "where'd it get installed?"
problems too, probably more so. r.tileset is more complicated than you
really want a shell script to be, but isn't so deep that it should be
written in C either. Somewhere in between.

Options I can think of:

1) change the r.tileset shebang to #!/bin/bash. Let the packagers of
platforms that don't supply bash in the normal place worry about
modifying the script + Make a note in the r.tileset help page.
At least there will be a useful help message and graceful exit if the
path is wrong.

2) keep #!/bin/sh, but add this within the script:

if [ -z "$BASH" ] ; then
   echo "$0: This script requires Bash." 1>&2
   exit 1
fi

3) Rewrite it in a language other than Bash.

#1 seems the most correct. #2 seems the most practical, but dirty.

Can we name any popular modern platform which doesn't keep bash in
/bin/bash?

Hamish

Hi,

  > #1 seems the most correct. #2 seems the most practical, but dirty.

Can we name any popular modern platform which doesn't keep bash in
/bin/bash?

IBM AIX 5 in the basic installation environment has "only" a ksh.

I would like to see python or perl to be THE scripting language of grass, because sh and even the bash have IMHO very limited capabilities to create sophisticated and maintainable code.
In case i learn python one day (i only know some basics), i will rewrite the grass test suite in python. The current bash based design is not very good maintainable ... .

Soeren

Hamish

_______________________________________________
grass-dev mailing list
grass-dev@grass.itc.it
http://grass.itc.it/mailman/listinfo/grass-dev

Hamish wrote:

2) keep #!/bin/sh, but add this within the script:

if [ -z "$BASH" ] ; then
   echo "$0: This script requires Bash." 1>&2
   exit 1
fi

Or:
  if [ -z "$BASH" ] ; then
      exec bash "$0" "$@"
      echo "$0: This script requires Bash." 1>&2
      exit 1
  fi

AFAICT, that should work so long as bash is called "bash" (and not
e.g. "bash2" or "bash-3.1.17") and is somewhere in the path.

--
Glynn Clements <glynn@gclements.plus.com>

Maybe

#!/usr/bin/env bash

instead of

#!/bin/bash

will solve the uncertainities of localization

2007/2/21, Glynn Clements < glynn@gclements.plus.com>:

Hamish wrote:

  1. keep #!/bin/sh, but add this within the script:

if [ -z “$BASH” ] ; then
echo “$0: This script requires Bash.” 1>&2
exit 1
fi

Or:
if [ -z “$BASH” ] ; then
exec bash “$0” “$@”
echo “$0: This script requires Bash.” 1>&2
exit 1
fi

AFAICT, that should work so long as bash is called “bash” (and not
e.g. “bash2” or " bash-3.1.17") and is somewhere in the path.


Glynn Clements <glynn@gclements.plus.com>


grass-dev mailing list
grass-dev@grass.itc.it
http://grass.itc.it/mailman/listinfo/grass-dev

Patricio Antonio Toledo Peña wrote:

#!/usr/bin/env bash

instead of

#!/bin/bash

will solve the uncertainities of localization

GRASS can't run in an empty environment. Actually, very little can run
in an empty environment, as $PATH, $HOME, $USER etc are all empty.

Besides, we *want* localisation (except when people are posting error
messages to the list).

--
Glynn Clements <glynn@gclements.plus.com>

Glynn Clements wrote:

Hamish wrote:

> 2) keep #!/bin/sh, but add this within the script:
>
> if [ -z "$BASH" ] ; then
> echo "$0: This script requires Bash." 1>&2
> exit 1
> fi

Or:
  if [ -z "$BASH" ] ; then
      exec bash "$0" "$@"
      echo "$0: This script requires Bash." 1>&2
      exit 1
  fi

AFAICT, that should work so long as bash is called "bash" (and not
e.g. "bash2" or "bash-3.1.17") and is somewhere in the path.

should we worry about the case where bash has been symlinked to ash
and the thing loops?

As long as it works with mac,cygwin,90% linuxes, I'm still leaning
towards simply changing the shebang to #!/bin/bash. I am happy to assume
BSD,IRIX,AIX,fringe linux folks will be capable enough to modify it
themselves if that's needed.

Hamish

Hamish wrote:

> > 2) keep #!/bin/sh, but add this within the script:
> >
> > if [ -z "$BASH" ] ; then
> > echo "$0: This script requires Bash." 1>&2
> > exit 1
> > fi
>
> Or:
> if [ -z "$BASH" ] ; then
> exec bash "$0" "$@"
> echo "$0: This script requires Bash." 1>&2
> exit 1
> fi
>
> AFAICT, that should work so long as bash is called "bash" (and not
> e.g. "bash2" or "bash-3.1.17") and is somewhere in the path.

should we worry about the case where bash has been symlinked to ash
and the thing loops?

No. It *could* happen, but it seems extremely unlikely.

I can't see what benefit symlinking bash to ash would achieve; any
script with #!/bin/bash (etc) is almost certain not to work with ash.

--
Glynn Clements <glynn@gclements.plus.com>