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 [email protected] "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 Answers 3

2

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 [email protected] \
"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.

3
  • 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' Commented Mar 16, 2017 at 15:38
  • @AnonymousPlatypus Sorry, I forgot about the ; at the end of the list in braces. It should be ok now.
    – user147505
    Commented Mar 16, 2017 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
    Commented Mar 17, 2017 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 [email protected] 'CHECK=/home/test/Desktop; until [ `cat $CHECK/samplefile | grep "string"` ]; do touch  $CHECK/success; done'
0
0
export CHECK='/home/test/Desktop'
ssh -n [email protected] 'until [ `cat "$CHECK/samplefile" | grep "string"` ]; do touch  "$CHECK/success"; done'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .