0

This question is a bit complicated. I will try to explain in detail.

I have two machines, one is local and other say 192.168.1.2. I have set the following variables in my local machine

CHECK="/home/test/Desktop/"

There exists a user named test in both my local machine as well as remote machine. I want to run the following command from my local over ssh.

ssh -n test@192.168.1.2 "until [ `cat $CHECK/samplefile | grep "string"` ]; do touch  $CHECK/success; done"

What I am trying to achieve is, I want to check the $CHECK/samplefile for the entry named "string" in my remote machine. Once it is found I want to exit the until loop and go further. But when I run this command I get the following error message.

cat: /home/test/Desktop//samplefile: No such file or directory

But I am pretty sure that my remote machine contain file name samplefile in test user's Desktop. On a further research I came to know that the conditional statement of until given in backquotes actually run at local instead of remote (My local doesn't contain such a file in Desktop). Also, the rest of the commands inside until loop works fine and a new file named success is created in remote machine's Desktop.

I am not sure whether the issue is with backquotes or until. I have been stuck on this for the past 3 hours. Any suggestions?

3

As you noticed in your question, this substitution:

`cat $CHECK/samplefile | grep "string"`

was executed at your local machine. You can fix it easily this way:

ssh -n test@192.168.1.2 \
"until { cat ""$CHECK""/samplefile | grep ""string""; }; do \
touch  ""$CHECK""/success; \
done"

As you can see, you don't need any substitution but for resolving the $CHECK variable. You can put the conditional instructions into a {...} list and the now the list's exit code is decisive for the until instruction.

  • I get bash: -c: line 0: syntax error near unexpected token do' bash: -c: line 0: until { cat /home/test/Desktop//samplefile | grep string }; do touch /home/test/Desktop//success; done' – Anonymous Platypus Mar 16 '17 at 15:38
  • @AnonymousPlatypus Sorry, I forgot about the ; at the end of the list in braces. It should be ok now. – Tomasz Mar 16 '17 at 15:49
  • You could use the single quotes inside the double like as follows: "until < '$CHECK/samplefile' grep 'string'; do touch '$CHECK/success'; done" since now that the backquotes have been taken out of the picture. – user218374 Mar 17 '17 at 7:27
2

You're right that it's the quoting. By using double-quotes to wrap your remote command in, you're telling your local shell to interpret whatever it can to pass to the ssh session. In this case, the cat command.

If you wrap your command in single quotes, you won't have that problem, but you also won't be able to expand variables that were defined outside the single quotes.

local file:

bash-[501]$ echo $(hostname) > /tmp/samplefile
bash-[506]$ echo $(cat /tmp/samplefile)
tank

create the remote file:

bash-[502]$ ssh evil 'echo $(hostname) > /tmp/samplefile'
bash-[501]$ cat /tmp/samplefile
evil

try to view the remote file with double-quotes:

bash-[508]$ ssh evil "echo `cat /tmp/samplefile`"
tank

try to view the remote file with single quotes:

bash-[509]$ ssh evil 'echo `cat /tmp/samplefile`'
evil

define the file as a variable to be processed on the remote side:

bash-[527]$ ssh evil 'F=/tmp/samplefile; cat $F'
evil

In your case, wrapping the command in single quotes, and defining $CHECK inside those quotes, out to be enough to send everything to be interpreted at the remote side.

ssh -n test@192.168.1.2 'CHECK=/home/test/Desktop; until [ `cat $CHECK/samplefile | grep "string"` ]; do touch  $CHECK/success; done'
0
export CHECK='/home/test/Desktop'
ssh -n test@192.168.1.2 'until [ `cat "$CHECK/samplefile" | grep "string"` ]; do touch  "$CHECK/success"; done'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.