92

stdout on one CentOS server needs to be piped to stdin on another CentOS server. Is this possible?

Update

ScottPack, MikeyB and jofel all have valid answers. I awarded the answer to Scott because, even though my question didn't specify security as a requirement, it's always nice to be safe. However, the other two fellows' suggestions will also work.

2
  • 1
    It's worth noting that the (only) major advantage of the non-ssh approach is throughput speed; if you're on a fast network and security is unnecessary this may be worth the extra inconvenience of typing two commands into two windows.
    – Random832
    Mar 16, 2012 at 12:53
  • Short answer to the question: yes, there are many ways to do this on every operating system.
    – masterxilo
    Apr 6, 2022 at 6:32

7 Answers 7

127

This is an unabashed yes.

When one uses ssh to execute a command on a remote server it performs some kind of fancy internal input/output redirection. In fact, I find this to be one of the subtly nicer features of OpenSSH. Specifically, if you use ssh to execute an arbitrary command on a remote system, then ssh will map STDIN and STDOUT to that of the command being executed.

For the purposes of an example, let's assume you want to create a backup tarball, but don't want to, or can't, store it locally. Let's have a gander at this syntax:

$ tar -cf - /path/to/backup/dir | ssh remotehost "cat - > backupfile.tar"

We're creating a tarball, and writing it to STDOUT, normal stuff. Since we're using ssh to execute a remote command, STDIN gets mapped to the STDIN of cat. Which we then redirect to a file.

11
  • 14
    That isn't any sort of "fancy internal input/output redirection" - just the plain, boring regular stuff. ssh reads from STDIN, just like any other tool, and passes it to the remote process. :) Mar 15, 2012 at 20:06
  • 7
    @DanielPittman: But it's just so much more fun to call it "fancy internal" garbage.
    – Scott Pack
    Mar 15, 2012 at 20:07
  • 7
    Similarly, netcat on both ends makes for a great simple, easy communication channel. tar cf - /path/to/dir | nc 1.2.3.4 5000 on one server, nc -l -p 5000 > backupfile.tar on the other.
    – MikeyB
    Mar 15, 2012 at 20:14
  • 1
    @MikeyB: Good point. Netcat is a clear-text protocol so be careful with sensitive data. I tend to use netcat for more specific things like network drive acquisitions (ala dd) over a local network and port scanning.
    – Scott Pack
    Mar 15, 2012 at 20:23
  • 2
    @MikeyB: You people what with your flying and your pants seats!
    – Scott Pack
    Mar 15, 2012 at 20:49
32

A convenient way of piping data between hosts when you don't need to worry about security over the wire is using netcat on both ends on the connection.

This also lets you set them up asynchronously:

On the "receiver" (really, you'll have two-way communication, but it's easier to think of it like this), run:

nc -l -p 5000 > /path/to/backupfile.tar

And on the "sender", run:

tar cf - /path/to/dir | nc 1.2.3.4 5000
3
  • 1
    Very good to know. This is good if the physical connection is trusted like perhaps a backup network or if the connection is already tunneled.
    – Wesley
    Mar 15, 2012 at 21:39
  • Or if the data is something that's public anyway. Mar 15, 2012 at 22:24
  • 1
    +1 netcat is an invaluable tool, especially when you don't have a ssh server running.
    – kwarrick
    Mar 15, 2012 at 23:31
22

A very powerful tool for creating uni- and bidirectional connections is socat. For a short look at the possibilities, look at the examples in its manpage.

It replaces netcat and similar tools completely and has support for ssl encrypted connections. For beginners, it might be not simple enough, but it is at least good to know that it exists.

1
  • 2
    @WesleyDavid: To your "Update": Just for completeness, I've added to my answer that socat has SSL support, so encryption is with socat possible, too. However, ssh is in most cases the better and easier solution, so I would have chosen ScottPack's answer,too.
    – jofel
    Mar 15, 2012 at 23:46
7

TL;DR

Things only get slightly more complicated when you have a bastion server that must be used.

  1. You can pass ssh as the command to ssh like so:

    • cat local_script.sh | ssh -A usera@bastion ssh -A userb@privateserver "cat > remote_copy_of_local_script.sh; bash remote_copy_of_local_script.sh"
  2. Beware of pseudo-terminals


Note that the point of key importance here is that ssh, like most tools, just treats stdout and stdin correct by default.

However, when you start to see option like Disable pseudo-terminal allocation. and Force pseudo-terminal allocation. you may need to do a little trial and error. But, as a general rule you don't want to alter tty behavior unless you are trying to fix garbled/binary junk in a terminal emulator (what a human types in).

For example, I tend to use -At so that my workstation's ssh-agent gets forwarded, and so that running tmux remotely doesn't barf binary (like so ssh -At bastion.internal tmux -L bruno attach). And, for docker too (like so sudo docker exec -it jenkins bash).

However, those two -t flags cause some hard to track down data corruption when I try to do something like this:

# copy /etc/init from jenkins to /tmp/init in testjenkins running as a container
ssh -A bastion.internal \
ssh -A jenkins.internal \
sudo tar cf - -C /etc init | \
sudo docker exec -i testjenkins \
bash -c 'tar xvf - -C /tmp'

# note trailing slashes to make this oneliner more readable.
3

Try to put your ssh public key in another host just by one command

ssh [email protected] 'cat >> .ssh/authorized_keys' < .ssh/id_rsa.pub
2

I find this to be the easiest, after setting up no password handshaking between servers for the user you are running the command as:

Uncompressed

tar cf - . | ssh servername "cd /path-to-dir && tar xf -"

Compression on the fly

tar czf - . | ssh servername "cd /path-to-dir && tar xzf -"
6
  • 1
    Using compression on the tar file is a very bad idea if your ssh is already configured for compression.
    – Anthon
    Feb 19, 2014 at 19:10
  • @Anthon Why so bad, and how would one check if ssh compression is already enabled?
    – Tom Hale
    Nov 1, 2016 at 9:11
  • 1
    @TomHale Depending on your systems speed, this might slow down the overall operation, as the second compression takes time, but is unlikely to shave of additional bytes. Compression could be set in any of the config files, a quick check for that is to see if ssh -v localhost exit 2>&1 | fgrep -i compress gives any output (AFAIK there is no option to dump the configuration as ssh has read it in).
    – Anthon
    Nov 1, 2016 at 9:31
  • tar has a -C path flag that works for both the c and x commands. You don't have to put a separate cd command in there. (But it is good to note that you can run more than a single command.) Feb 21, 2017 at 16:07
  • @Bruno, -C is a GNU extension (though now also supported by bsdtar and schily tar) Feb 21, 2017 at 16:34
1

For moving some docker images around, or VPN .conf files; sometimes I do this:

from local to remote

docker save alpine:latest | ssh remote-host "cat - | docker import - alpine:latest"
  • docker save alpine:lates export or save file
  • ssh remote-host ssh to remote-host
  • cat - | read from STDIN and pipe it
  • docker import - alpine:latest read from STDIN and save it

Then alpine:latest will be available on remote-host

from remote to local

docker import - getmeili/meilisearch < <(ssh remote-host docker save getmeili/meilisearch)
  • ssh remote-host ssh to remote-host
  • docker save getmeili/meilisearch run this command
  • <(CMD) redirect the output back to STDIN
  • < read from STDIN
  • docker import - getmeili/meilisearch read from STDIN

Then getmeili/meilisearch will be available on local host.

from remote to another remote (by help of a local)

cat - < <(ssh remote-host-1 "cat /home/pf/configs/shf.conf") | ssh remote-host-2 "cat - > /tmp/shf.conf"

In this style, I download shf.conf file from the remote-host (1) and without write it to desk sent it to another remote-host (2).

[ remote-1 ] => [ local (mypc)] => (remote-2)

Actually we can omit cat - < and use:

ssh remote-host-2 "cat - > /tmp/shf.conf" < <(ssh remote-host-1 "cat /home/pf/configs/shf.conf")

And this also sends newline if we be prompt for password , so the third version is better:

ssh remote-host-1  "cat /home/pf/configs/shf.conf" | ssh remote-host-2 "cat - > /tmp/shf.conf"

You must log in to answer this question.

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