Sending terminal commands via SSH connection: Nested pipes

0

1

Hoi everybody,

I am currently having a problem with sending commands over SSH via command line to a server. To have an easy example, I always send the "pwd" command - which should return the current folder you are in.

I build the initial SSH connection successfully with the following command:

sshg3 user@server#port 'pwd'

which connects to the server and short the home folder.

Afterwards, I use sudo su - user2 - because the user has more rights as user (needed for specific tasks):

sshg3 user@server#port "echo pwd|sudo su - user2"

Here, however, if I want to concat multiple commands after one another, I need to insert "" - otherwise it does not work:

sshg3 user@server#port "echo ""pwd;pwd""|sudo su - user2"

If I have no or only one ", the result is:

pwd
-bash: line 1: {homefolder}: is a directory

Now, afterwards using lftp I need to upload data to that server using yet another user. Using another pipe, I get that to work with a single command the following way:

sshg3 user@server#port "echo ""echo pwd|lftp -u user3 -p 1234 server2""|sudo su - user2"

And now comes the problem: Sending multiple commands to the second server does not work. If I use the same pattern I used before (""), I get this result:

sshg3 user@server#port "echo ""echo ""pwd;pwd""|lftp -u user3 -p 1234 server2""|sudo su - user2"

This prints:

echo pwd
bash: pwd|lftp -u user3 -p 1234 server2: command not found

The most part I got by using the answer in [this][1] thread - but now I am stuck.

Can someone help me with this?

bublitz

Posted 2018-08-24T09:11:18.737

Reputation: 1

What is your local shell? I think "echo ""pwd;pwd""|sudo su - user2" is equivalent to "echo pwd;pwd|sudo su - user2" because of how the shell parses it. Did you mean \"? – Kamil Maciorowski – 2018-08-24T09:23:58.540

Additionally I cannot tell what exactly you are trying to do. Maybe if I knew what "this thread" is... Please [edit] the question and at least fix the link. – Kamil Maciorowski – 2018-08-24T09:29:11.163

Still I'm not sure what the command should do and I have no experience with lftp. But I know these echo-s are awful. Do you need su to provide you an interactive shell after lftp finishes? Something like this seems to be a way better syntax: sshg3 user@server#port 'sudo -u user2 -- lftp -u user3 -p 1234 -c "pwd; pwd" server2'. Untested though. – Kamil Maciorowski – 2018-08-24T09:50:33.943

Answers

0

I am not exactly sure what you are trying to do on the remote server. It looks like you want to execute commands which depend on the response of other commands (like pwd, which prints the working directory). Possibly you also want to use a password ("echo pwd") for su, I am not sure which.

I would suggest one of the following approaches:

  • Write a script on the remote server that does what you want. Execute that script via ssh. Give the script additional information, like passwords, as arguments when you call it.

  • If you can't store the script on the remote server permanently: Write the script anyway, and then pipe and execute the whole script through ssh.

  • Use expect to script a complicated interactive session via ssh, where you call various programs, which in turn expect user input.

In any case, I don't think you'll get far messing around with echo.

dirkt

Posted 2018-08-24T09:11:18.737

Reputation: 11 627

0

I think you've got an XY problem. If you could tell us what you're trying to achieve rather than how you're trying to achieve it, then we could probably help out...


In the meantime, as I can't help with your original problem, let's address the following:

sshg3 user@server#port "echo ""echo ""pwd;pwd""|lftp -u user3 -p 1234 server2""|sudo su - user2"

Bash will break this into arguments based on unquoted whitespace, thus the arguments are:

  1. sshg3
  2. user@server#port
  3. "echo ""echo ""pwd;pwd""|lftp -u user3 -p 1234 server2""|sudo su - user2"

After removal of the quoting from argument 3, it will look like this: (I don't think that's what you intended)

echo echo pwd;pwd|ltfp -u user3 -p 1234 server2|sudo su - user2

You can confirm this with the following snippet.

Put your command into the array with X=( YOUR_COMMAND ):

$ X=(sshg3 user@server#port "echo ""echo ""pwd;pwd""|lftp -u user3 -p 1234 server2""|sudo su - user2")
$ for i in "${X[@]}"; do echo "${i}"; done
sshg3
user@server#port
echo echo pwd;pwd|lftp -u user3 -p 1234 server2|sudo su - user2

The cleaned version of argument 3 will be passed to the remote system and will (probably) be interpreted like so:

  • Command 1 arguments:

    1. echo
    2. echo
    3. pwd
  • Command 2 arguments: (stdout wired to Command 3's stdin because of pipe / |)

    1. pwd
  • Command 3 arguments: (stdout wired to Command 4's stdin)
    1. lftp
    2. -u
    3. user3
    4. -p
    5. 1234
    6. server2
  • Command 4 arguments:
    1. sudo
    2. su
    3. -u
    4. user2

Again, you can confirm this by logging in and running the cleaned third line from the remote shell.


There are a few things to note about this:

  • You probably didn't mean to echo echo pwd to stdout (which is what Command 1 will do)
  • lftp won't expect an absolute path (and nothing else) to be given on stdin
  • su very likely won't expect whatever the output of lftp is to be given on stdin... su will invoke user2's shell.

Attie

Posted 2018-08-24T09:11:18.737

Reputation: 14 841