/bin/sh bad syntax in for loop - bash

I'm trying to run this script in my synology wit /bin/sh, it's all I have.
And while the script is working fine in normal /bin/bash environment, Synology is showing this error:
/volume2/myCustomPath/rotatingSnapshots.sh: line 22: syntax error: bad for loop variable
This is the code, the line which Synology is complaining about is the first one:
for (( i=$BIGGEST_NUMBER; i>=1; i-- ))
do
## Some code here
done
Any ideas? I can't find what is wrong.

/bin/sh refers to the POSIX shell. You're trying to use bash syntax in your script sp you should ideally be using the bash shell. This should work for you-
(Incidentally, you also don't need the $ in the loop).
#!/bin/bash
for (( i=BIGGEST_NUMBER; i>=1; i-- ))
do
## Some code here
done

Related

Cron doesn't accept bash syntax

I have a bashscript that I'm running with crontab. Unfortunately, a script that works fine when run manually fails with the error:
Syntax error: "(" unexpected (expecting "}")
Where the line in question is line 22 which is:
declare -a PREV_TOTAL=( $(for i in ${range[#]}; do echo 0; done) )
In the larger context:
TOTAL_CPU_USAGE=0
TOTAL_CPU=$(grep -c ^processor /proc/cpuinfo) #set number of CPUs to check for
declare -a 'range=({'"0..$TOTAL_CPU"'})'
let "TOTAL_CPU=$TOTAL_CPU - 1"
#declare array of size TOTAL_CPU to store values (eg. 8 cpus makes arrays of size 8)
declare -a PREV_TOTAL=( $(for i in ${range[#]}; do echo 0; done) )
declare -a PREV_IDLE=( $(for i in ${range[#]}; do echo 0; done) )
This works when manually just fine, but I don't understand what I'm doing wrong that causes cron to give this error? If you know I'd be very appreciative. Thanks.
EDIT: My crontab looks like this:
# m h dom mon dow command
SHELL=/bin/bash
#reboot cd /home/ubuntu/waste-cloud-computing/probe && probe.sh >> /var/log/somelogfile.log 2>&1
And I access it with sudo crontab -e. I'm still getting the issue while providing the SHELL variable.
EDIT 1: Thanks to some help I got past the syntax issues by ensuring the shell was using bash. Now I get the error, /bin/bash: probe.bash: command not found. I assume its some kind of PATH issue, but which bash returns /bin/bash so it seems normal to me. Maybe someone knows what's up?
cron jobs are run by sh by default, not bash. If you are using ubuntu/vixiecron, you can set the SHELL env variable at the top of the crontab to make cron run the commands in your crontab with bash.
SHELL=/bin/bash
If the script you want to be run is a bash script, make sure you have a shebang at the first line:
#!/bin/bash
Also note that there will be other potential troubleshooting steps if your scripts depend on a particular user's profile, env vars, etc. depending on which crontab you are editing.
Thanks to the help of the people here I found my issue was not syntax but rather the use of sh over bash. This was fixed by setting the crontab this way so future users can see:
# m h dom mon dow command
SHELL=/bin/bash
#reboot cd /home/ubuntu/waste-cloud-computing/probe && ./probe.sh >> /var/log/somelogfile.log 2>&1
The key points are the SHELL variable being set and the ./ before running the script.

Shell script: unexpected `(' [duplicate]

I have written the following code:
#!/bin/bash
#Simple array
array=(1 2 3 4 5)
echo ${array[*]}
And I am getting error:
array.sh: 3: array.sh: Syntax error: "(" unexpected
From what I came to know from Google, that this might be due to the fact that Ubuntu is now not taking "#!/bin/bash" by default... but then again I added the line but the error is still coming.
Also I have tried by executing bash array.sh but no luck! It prints blank.
My Ubuntu version is: Ubuntu 14.04
Given that script:
#!/bin/bash
#Simple array
array=(1 2 3 4 5)
echo ${array[*]}
and assuming:
It's in a file in your current directory named array.sh;
You've done chmod +x array.sh;
You have a sufficiently new version of bash installed in /bin/bash (you report that you have 4.3.8, which is certainly new enough); and
You execute it correctly
then that should work without any problem.
If you execute the script by typing
./array.sh
the system will pay attention to the #!/bin/bash line and execute the script using /bin/bash.
If you execute it by typing something like:
sh ./array.sh
then it will execute it using /bin/sh. On Ubuntu, /bin/sh is typically a symbolic link to /bin/dash, a Bourne-like shell that doesn't support arrays. That will give you exactly the error message that you report.
The shell used to execute a script is not affected by which shell you're currently using or by which shell is configured as your login shell in /etc/passwd or equivalent (unless you use the source or . command).
In your own answer, you say you fixed the problem by using chsh to change your default login shell to /bin/bash. That by itself should not have any effect. (And /bin/bash is the default login shell on Ubuntu anyway; had you changed it to something else previously?)
What must have happened is that you changed the command you use from sh ./array.sh to ./array.sh without realizing it.
Try running sh ./array.sh and see if you get the same error.
Instead of using sh to run the script,
try the following command:
bash ./array.sh
I solved the problem miraculously. In order to solve the issue, I found a link where it was described to be gone by using the following code. After executing them, the issue got resolved.
chsh -s /bin/bash adhikarisubir
grep ^adhikarisubir /etc/passwd
FYI, "adhikarisubir" is my username.
After executing these commands, bash array.sh produced the desired result.

bash config syntax error

I'm setting up a brand new VPS on Bluehost. As soon as I logged in, I knew something was amiss. When I launch a bash shell I get this error:
bash: eval: line 9: syntax error: unexpected end of file
I tracked the problem down to the line eval $(perl -Mlocal::lib) in /etc/profile.d/locallib.sh:
#cPanel Added local::lib -- BEGIN
LOCALLIBUSER=$USER
if [ -e "/usr/bin/whoami" ]; then
LOCALLIBUSER=`/usr/bin/whoami`
fi
if [ "$LOCALLIBUSER" != "root" ]; then
eval $(perl -Mlocal::lib)
fi
#cPanel Added local::lib -- END
When I execute eval $(perl -Mlocal::lib) at the bash prompt, I get the error bash: syntax error: unexpected end of file. When I execute perl -Mlocal::lib at the bash prompt I get this:
if ! $?PERL_MB_OPT setenv PERL_MB_OPT '';
setenv PERL_MB_OPT "--install_base "\""/home/MYUSERNAME/perl5"\""";
if ! $?PERL_MM_OPT setenv PERL_MM_OPT '';
setenv PERL_MM_OPT "INSTALL_BASE=/home/MYUSERNAME/perl5";
Why am I getting this error? How do I correct it? I'm relatively new to bash and utterly hopeless with perl, so am on shaky ground here. Thanks!
The code inside local::lib is misidentifying your shell as csh for some reason. You can force it with --shelltype bourne according to the documentation.
eval $(perl -Mlocal::lib=--shelltype,bourne)
I'm speculating that your account may have been set up with tcsh as your default shell. You can change this permanently with chsh, in which case this workaround should hopefully not be necessary.

Bash for loop has syntax error only when run from a ruby script

I have a Ruby script that orchestrates a number of other scripts. One of the bash scripts pulls log data from a server, and a ruby script then parses them.
My bash script looks something like this:
#pullLogs.sh
for ((x = $2; x <= $3; x++)); do
# creates a subdirectory for each server number
rsync --progress -rvze ssh name#$ARCHIVE_SERVER:/path/to/log/$logDate.gz $x/
done
for ((x = $2; x <= $3; x++)); do
cd $x
for z in *.gz; do gunzip $z; done
cd ..
done
cd ..
What this script does is pulls logs from a given date, from specified servers. Usually there are ten servers, so the script will pull from server 1, then from server 2, etc etc.
This script works perfectly if I specify the desired date from the command line
./pullLogs.sh desired_date 1 10
successfully pulls all the logs from the desired date from all ten servers.
However, I want to pull all the logs from todays date to some past date, and parse each one. So I use this ruby script:
while upload_day != $DESIRED_DATE do
args = "#{year}#{month}#{day} 1 10"
`bash -c ./#{path_to_pullLogs_sh} #{args}`
`ruby #{name_of_followup_ruby_script}`
upload_day = upload_day.prev_day
end
The ruby script iterates through the correct days and calls the correct bash script (the one given above). However, after running the bash script, it produces an error:
./pullLogs.sh: line 15: ((: x = : syntax error: operand expected (error token is "= ")
./pullLogs.sh: line 21: ((: x = : syntax error: operand expected (error token is "= ")
So when I run it from the console, the loop variables 1 and 10 are good, but when I run it from the ruby script, it finds a problem with my syntax
How can make this work?
Drop the -c from your call to bash. This causes ./#{path_to_pullLogs_sh} to be used as the command to run, and the following arguments are passed as shell arguments starting with $0, not $1, meaning your script is short one argument.
`bash ./#{path_to_pullLogs_sh} #{args}`
(This works for the same reason as Z1MM32M4N's comment; it causes bash to treat ./pullLogs.sh as a script to run, rather than a string containing a snippet of shell code to execute.)

syntax error near unexpected token `((' in Sun Solaris Unix

I have the following logic in the script Setup.sh.
#!/bin/bash
for ((i = 0 ; i < 5 ; i++))
do
echo "Welcome $i times."
done
When I run the script using the command ./Setup.sh, I get the error
./Setup.sh: line 3: syntax error near unexpected token `(('
./Setup.sh: line 3: `for ((i = 0 ; i < 5 ; i++))'
When I run the script using the command sh Setup.sh , I get the error
Setup.sh: syntax error at line 3: `(' unexpected
When I run the script logic in Execute BASH Shell Script Online using http://www.compileonline.com/execute_bash_online.php, it executes perfectly and prints the following.
Welcome 0 times.
Welcome 1 times.
Welcome 2 times.
Welcome 3 times.
Welcome 4 times.
Can someone help me understand why I get this error on Sun Solaris Unix machine?
When you run sh Setup.sh the Solaris /bin/sh is used to execute the script. The Solaris /bin/sh is not a POSIX shell and also does not understand the non-portable (()) syntax.
If you use #!/bin/bash it should work. If it doesn't, maybe your bash is very ancient. What does bash --version output?
The online demo uses bash 4.1.2(1)-release.
Please check which version of bash you have on the Solaris system.
bash --version
As far as I remember, the (( )) arithmetic notation was introduced recently. And it's a bashism, so it does not work with sh.
The website probably uses a new version of bash.

Resources