Syntax error for '&' in a remote command - bash

I want to ssh to a node and run a program in a background using &. So, the script looks like
#!/bin/bash
ssh NODENAME 'lmgrd -c license.lic &;
exit;'
However, the bash interpreter complains for syntax error near unexpected token ;. It seems that &

& already finisheds a command. So after & you simply don't use any terminator.

Related

Syntax error near unexpected token `;' when running a command in Bash

In Bash in the terminal, it is impossible to run a command that ends with and & (being sent to the background) followed by another command (obviously with a ; between them). Why is that? Why can't you run anything with &; or $ ; in it?
I'm trying to recreate a 502 error and was trying to DoS a specific page in a testing server. I was trying to run this:
while true; do curl -s https://some.site.com/someImage.jpg > /dev/null &; echo blah ; done
as a "one-liner" in the terminal. However, I got this error:
-bash: syntax error near unexpected token `;'
However the commands work individually, and when I run the curl command not in the background it works as a loop as well. It also works when it write a one line script, "/tmp/curlBack.sh" that includes only
curl -s https://some.site.com/someImage.jpg > /dev/null &
And then run
while true; do bash /tmp/curlBack.sh ; echo blah ; done
Why am I getting this error and how do I fix it?
The problem is with the semi-colon after the ampersand (&):
An ampersand does the same thing as a semicolon or newline in that it indicates the end of a command, but it causes Bash to execute the command asynchronously.
BashSheet
Basically, it's as if you were to put double semi-colons back to back, that would cause a syntax error too.
To fix this problem, you simply need to remove the semi-colon, I tested it that way and it seems to be working:
while true; do curl -s https://some.site.com/someImage.jpg > /dev/null & echo blah ; done

cygwin ssh via windows cmd removes double quotes

I've got two windows machines running the latest version of cygwin. I have OpenSSH configured on both of them, and password-less authentication has been set up for the remote machine. I can ssh into either machine without problems. All commands below are executed in cmd.exe.
System Specification (identical for both machines):
Cygwin version 1.7.32
Windows 7
ver from cmd returns "Microsoft Windows [Version 6.1.7601]"
R 2.14.1
The basic form of my problem is this. I have to start an executable on my remote machine. I must start this executable via ssh through windows command line, not cygwin. That executable has a couple parameters. One of these parameters needs to be encapsulated within double quotes (Because I am working with a third party package in R, which makes a call to system(), and one parameter expects a string). The actual parameter is -e "parallel:::.slaveRSOCK()"
The script.exe called below is the file Rscript.exe. This comes with any (to my knowledge) installation of R. I did not create it, compile it, or anything. It is just utilized by the package I am trying to debug, as it allows you to execute R commands outside of the R console gui. The package I am trying to debug is "parallel", which I am using to run parallel processes on remote machines. I also did not have any hand in creating or compiling this code.
Maybe needless additional info, but the portion of the package I'm trying to debug is the function that spins up a process on a remote machine. This function develops a command, given some parameters, and executes this command in cmd.exe. I'm trying to replicate the command and manually execute, as when running through the actual package the process simply hangs.
If I were starting the executable on my machine, I would do the following, in windows cmd.
C:\Path\script.exe -e "parallel:::.slaveRSOCK()"
And this works fine. Establishing an ssh connection to the remote machine and subsequently running this command (changing C to c) also works.
But, when I make the following call for starting this script on the remote machine from my machine
ssh remoteHost c:/Path/script.exe -e "parallel:::.slaveRSOCK()"
I get the following error
bash: -c: line 0: syntax error near unexpected token '('
bash: -c: line 0: 'c:/Path/script.exe -e parallel:::.slaveRSOCK()'
So I've lost the double quotes, obviously I'm not escaping them correctly. I've tried the following call. which was close
ssh remoteHost c:/Path/script.exe -e \"parallel:::.slaveRSOCK()\"
but the second line of the error gave me
bash: -c: line 0: 'c:/Path/script.exe -e \parallel:::.slaveRSOCK()"'
Doesn't make a whole lot of sense to me, as I managed to escape the second quote but the first disappears, and I'm left with a \ before parallel.
EDIT
This one, as suggested in one of the answers
ssh remoteHost "c:/Path/script.exe -e \"parallel:::.slaveRSOCK()\""
gave me the following error
bash: -c: line 0: 'c:/Path/script.exe -e \parallel:::.slaveRSOCK()\'
Also quite an odd result, we lose both double quotes but keep the escapes
I've also tried various combinations of double quotes (single quotes) around the whole command after ssh remoteHost, and using the ^ to escape , but now it has pretty much turned into taking shots in the dark, so I thought it may be a good idea to turn to people more knowledgeable than me.
Any help or insight that can be provided is much appreciated. If there are any questions let me know.
EDIT 2
Here are some simple examples of the odd escaping that's going on.
Call:
ssh otherhost echo \"hello()\"
Returns:
bash: -c: line 0: unexpected EOF while looking for matching '"'
bash: -c: line 0: syntax error: unexpected end of file
Call:
ssh otherhost echo \"hello()"
Returns:
hello()
Call:
ssh otherhost echo '\"hello()\" '
Returns:
"hello()"
Call:
ssh otherhost echo "\"hello()\""
Returns:
hello\(\)
Alternatively, an explanation of this behavior would be appreciated.
I think you want:
ssh remoteHost "c:/Path/script.exe -e \"parallel:::.slaveRSOCK()\""
I honestly can't fully explain the reasoning behind the quoting (or what's screwing it up if it's a bug), but I think this will work for you:
ssh remoteHost "c:/Path/script.exe -e \"parallel:::.slaveRSOCK\(\)\""
The complication seems to be the following sequence of things parsing the command line(s):
Windows cmd.exe on the local machine gets and parses the whole thing
ssh sends the "c:/Path/script.exe -e \"parallel:::.slaveRSOCK()\"" portion to sshd on the remote Windows host. I'm not sure in what form sshd gets this command line, or exactly what transformations it might do to it.
sshd apparently invokes bash to run the command (thorough some cygwin mechanism?). Again, I'm not sure of the exact form the command line that gets to bash.
bash gets confused unless the parens are escaped, and the backslashes seem to get far enough through this assembly line of processes to make bash on the remote windows-with-cygwin machine happy.

Whats wrong with this list of servers in my bash script?

I am writing a simple bash script (checkServs.sh) that will ssh into a list of servers and perform a health check on them.
I keep getting errors on the following line:
SERVERS=(blah1.example.com blah2.example.com blah3.example.com blah4.example.com)
Error is:
checkServs.sh: 3: checkServs.sh: Syntax error: "(" unexpected
I've checked online examples and this seems correct, isn't it? Thanks in advance!
I don't know about the syntax error, but this should work:
SERVERS="blah1.example.com blah2.example.com blah3.example.com blah4.example.com"
for server in $SERVERS
do
echo $server
done
EDIT: As noted by Jonathan Leffler in a comment, maybe you are not running the script with bash. Other shells, such as dash, may not recognize the array syntax. If that's the case, you can do:
SERVERS=(blah1.example.com blah2.example.com blah3.example.com blah4.example.com)
for i in $(seq 0 3)
do
echo ${SERVERS[$i]}
done
But if you just want to loop through the names and run an SSH command (ie if having an array won't provide useful functionality), the first method is more straightforward.
Your remote server probably calls a different shell when executing commands. Try to add bash -c to your arguments:
ssh user#server bash -c "<your commands>"
Or:
ssh user#server bash < yourscript.sh ## None in yourscript.sh must read input though.
An opening parenthesis starts a subshell, which is not a correct thing to have on the right side of an equals sign. It expects a string expression, not a command.
Quotation marks are used to keep a string expression together.

sudo bashfile makes syntax error

i have got a bash file which i want to toggle via the sudo crontab list. Problem is, that it does not work, because when i run the script with sudo, there is a syntax error message on this line:
size=(`du -h $backupDir --summarize`)
If i run the same script without, i have to type the sudo pw, but it works without any problems.
I allready tried a few variations with brackets, with or without backticks, with or without spaces, etc but nothing helped. The error message is:
Syntax error: "(" unexpected (expecting ";;")
Any help?
The problem here is that you use bash-syntax, and the script (when it is executed from cron) is interpreted by /bin/sh (that known nothing about arrays and the () construction.).
You must either specify bash as an interpreter of the script using she-bang notation:
#!/bin/bash
or run the script explicitly with bash from cron:
bash /path/to/script
or rewrite script so, that it could run without arrays.
Fro readability use the $() form
size=$(du -h $backupDir --summarize)
If you want to stick to back quotes, then
size=`du -h $backupDir --summarize`

Why do I get "unexpected token `;'?

I would like to run a few instances of my bash script foo.bash in background.
When I write for i in {1..10}; do ~/bin/foo.bash & ; done in the command line I get an error: bash: syntax error near unexpected token ;
Could you explain why this error occurs and how to fix the command?
& and ; are both command separators; you don't need (and can't have) both.
for i in {1..10}; do ~/bin/foo.bash & done

Resources