Unexpected "(" (expecting "}")

Hi all,
I run the script runvdr from the package runvdr-extreme for many years without any problem (I'm not allowed to post links, but it should be easy to find). Now I tried to run it from within LibreElec which gives me the following error

unexpected "(" (expecting "}")

. The corresponding line contains

ADDPARAMS=()

where ADDPARAMS describes an array.
I tried to run the script with an explicit /bin/bash without any changes.
My skills in scripting are extreme limited and I don't know if it's possible to locate the error without being able to run it on LibreElec but maybe someone has the sparkling idea.
Thanks in advance
Alex

Hi Alex,
Welcome to the UNIX.com forum.

When starting a new thread here, please always tell us what operating system you're using and what shell you're using. Various common utilities behave differently on various operating systems and when run by various shells. Many utilities have options that are available on some operating systems but not on others. If we don't know what environment you're using, we have to guess at what might be happening to you.

You say that you have been running runvdr for years. What has changed since the last time you ran it successfully? Did you install any new software packages, system or application updates, start using a different shell?

What exact command did you use to invoke runvdr ?

Exactly what diagnostic messages did it produce when you invoked it?

When the shell tells you it was expecting a } , it usually means that sometime before it issued that complaint it had found a { and it hasn't found a match for it yet to finish what it had been told to do. With the complete diagnostic message and the contents of the script you're running, we might have a much better chance of helping you figure out what happened.

1 Like

Hi Don Cragun,
thanks for your answer.
Actually I told you what operating system I (want to) use: LibreElec. It's a JustEnoughOS based (I guess) on Linux from scratch.
Maybe this was misleadingly formulated.
The same script without any changes is running (for years) on the pc I'm working on. Current OS is Ubuntu Trusty. So it's not the script that changed, it's just that I want to run it on LibreElec.
LibreElec uses busybox, but bash is installed.
The script is executable so normaly I run it by invoking runvdr, but as I wrote I also tried /bin/bash /usr/bin/runvdr.
The only diagnostic message is the error message telling me that line 204 produces the error

Unexpected "(" (expecting "}") 

The script itself is definitely too large to be posted here.
As the script is running on other pc's without any problems I don't think that there's a matching } missing. I found that arrays are handled different in different shells. That's why I tried /bin/bash, the shebang is correct too. So I wonder if the code can be changed so that it's more "universal". Is unset somearray the same as somearray=() ?

So you said this code had been running for years and nothing had changed, but what has changed is that you're trying to run it under a different operating system. That is a HUGE difference.

What version of bash is installed on the system(s) where runvdr is working?

What version of bash is installed on busybox on LibreElec?

You said the shebang is correct... please show us the exact contents of the first line of runvdr .

Can code that is written to run with a specific version of a specific shell be rewritten to be more universal? Probably. Will changing the single line of code:

ADDPARAMS=()

in a script that is too big to post fix the problem? Almost certainly not. And, believe it or not, the shell that is attempting to run runvdr is telling you that it is looking for a } when it gives you that diagnostic message. It is saying that it gave up looking for the } and reported the error when it found the ( in the array assignment statement. The array assignment is not necessarily the problem; it is just where that shell determined that it was lost while trying to interpret that script.

I've managed to find the script you are talking about from runvdr 0.5.0. I've cut it down to a 59 line script that contains the spirit of what is going on:

#!/bin/bash
RUNVDR="${0##*/}"
RUNVDRCONF=""

# Some unix commands being used:

PS="ps"
GETOPT="getopt"

which $PS        >/dev/null || { echo missing $PS... >&2 ;      exit 1 ; }
which $GETOPT    >/dev/null || { echo missing $GETOPT... >&2 ;  exit 1 ; }

function ParseCommandLine_Step1() {
    SHORTOPT="a:c:C:dD:E:g:hi:l:L:mp:P:r:s:t:u:v:Vw:"
    LONGOPT="runvdr-conf:,xserver-proxy:,pluginsetup-conf:,setupplugin-conf:,vdr:,\
        switchterminal:,maxrestarts:,restarttime:,xserver:"

    # prepare all optios for later processing
    OPTIONS=`$GETOPT -o "$SHORTOPT" --long "$LONGOPT" -n "$0" -- "$@"` || exit 1

    eval set -- "$OPTIONS"

    XSERVERPROXY=
    while true ; do case "$1" in
        -C|--runvdr-conf)  RUNVDRCONF="$2";  shift 2;;
           --xserver-proxy) XSERVERPROXY="$2"; shift 2;;
           --pluginsetup-conf)               shift 2;;
           --setupplugin-conf)               shift 2;;
           --vdr)                            shift 2;;
           --switchterminal)                 shift 2;;
           --xserver)                        shift 2;;
        --)
            shift
            break
            ;;
        *)
            echo "Internal error!" >&2
            exit 1
            ;;
    esac ; done
}

function Clean() {
    # Clean all config variables
    ADDPARAM=
    ADDPARAMS=()
    PLUGINSETUPCONF=
    SETUPPLUGINCONF=
}

#### ---------------
####   Main script
#### ---------------

# Parse command line, step 1
ParseCommandLine_Step1 "$@" || exit 1

# Clean variables
Clean

Are you getting the same error on line 46 of this script?

5 Likes

The Bash version of Libreelec is 4.3.46, busybox 1.30.0.
The bash version that's working is 4.3.11

Thanks for your efforts.

Please give me some time, will have a look ASAP.

Does your busybox version really offer bash ? Mine doesn't:

but sh ( ash ) is there. And sh doesn't have arrays.
So, if I run above Clear function definition (thanks Chubler_XL for providing) in busybox, I get

sh: syntax error: unexpected "(" (expecting "}")

Are you sure you posted the entire error message in post #1?

busybox bash is not bash, not even if it calls itself that. That's just a convenience alias to a more limited shell.

Install bash.

LibreELEC:~ # /bin/bash /storage/.config/test
/storage/.config/test: line 46: syntax error: unexpected "(" (expecting "}")

That's what I wrote in my second post.

I only said that bash is installed
but after I read Corona's comment

I doublechecked and bash --version really results in an empty line.
So is it true that busybox offers a fake bash command? That's irritating (as well as the error message)

LibreElexc is compiled from scratch, where the contend is controlled by package descriptions. There definitely is a package for bash 4.3.46 but obviously it wasn't compiled and installed. I'll have to look into this.

So if this

Currently defined functions:
        ar, arch, arp, arping, ash, awk, basename, bash 

is just a limited bash version and there is no way to change the code of the script because busybox offers no arrays then this problem should be "solved". Learning never stops.
I thank you all for your efforts and useful contributions.

It's kind of a "boy who cried wolf" situation. bash and sh are so synonymous in the linux world, it's difficult to convince authors to type #!/bin/sh whenever #!/bin/bash wasn't needed. On many systems, they're the exact same thing anyway, they have no "minimal" shell to even test with.

But in a system with 2 megs of storage and 4 megs of RAM, bash is a "hog". Many hundreds of kilobytes could be saved by using a more minimal shell. So they install busybox, plus the link to make these "bash" scripts run on vanilla sh, which is usually enough to work, sometimes with a minor modification or two.

Of course, on the rare occasion these "bash" scripts actually need bash, you get this.

I fully understand why busybox is used on systems like JustEnoughOSes, after all that's the reason why I use LibreElec.
But it would be very helpfull if at least error messages would give a tiny hint that it's busybox that produces that error and not bash. It's not obvious that if you type an explicit command like /bin/bash that you end up in a "fake" version.
But that' another story.

I fully agree with you there. Note that if you were using a real bash , any diagnostic messages that it produces would include " bash: " at the start of the message. For example if I issue the command:

bash -c 'for i in *;do { cat "$i'

on macOS, I get two diagnostics:

bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file

each of which clearly indicates that the diagnostic came from bash (the first indicating that it is looking for a missing <double-quote> character and the second indicating that it is looking for a missing } and/or a missing done ). This is why we asked you to be sure that you were showing us the exact, complete diagnostic messages you were getting when you reported the problem.

If the tools provided by busybox don't do that for you, you'll have a hard time trying to guess if the diagnostics you're seeing are coming from the shell or from one of the utilities invoked by the shell. This makes diagnosing problems in an environment like that much more difficult for you. I wish you luck.

Thanks.
I will need it :wink: