Authors Top

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

1. Introduction

Remote access to systems is more common than ever. However, due to different limitations of protocols and environments, general and clipboard data sharing may not always be available out of the box between client and server machines.

In this tutorial, we discuss how we can transfer data locally from a remote SSH session in Linux. First, we briefly clarify what SSH is and how we use it. Next, we explain how we can redirect the output of interactive and non-interactive sessions. Finally, we conclude with the specific case of redirecting to the clipboard.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It is POSIX-compliant and should work in any such environment.

2. SSH Protocol

Secure Shell (SSH) is a cryptographic network protocol for secure information transfer.

For our purposes, we’ll assume SSH keys are already:

This means default key access is readily available, and we’ll skip authentication in our ssh (Secure Shell) client commands.

Since authentication is the main hurdle, with configured key access, using ssh becomes trivial.

3. SSH Remote Execution Modes

Broadly speaking, we can use ssh to run one or more commands and exit or initiate an interactive session and wait for input. For our needs, the latter scenario is more complex. Let’s briefly discuss both of them.

3.1. Interactive

In interactive SSH session mode, we enter commands at the prompt, but all of them execute on the remote machine:

$ hostname
$ ssh [email protected]
$ hostname

Here, we use hostname to output the current machine’s hostname. After that, we enter a remote interactive SSH session with user x on the server, where we show that the hostname returned by the same command is that of the remote system.

The SSH protocol achieves this by just executing the default shell on the remote machine, which takes over the whole SSH session. Exiting this interactive session terminates the shell as well as the ssh client process and returns control to the terminal, where we started it.

3.2. Script

One of the SSH protocol’s many features is remote command execution:

$ hostname
$ ssh [email protected] 'hostname'

Basically, we skip the interactive capabilities of ssh and just execute the provided command or commands, returning the output. Note how the command is supplied as an argument.

We’ll examine both execution modes in detail. Let’s continue with the non-interactive script mode.

4. Non-Interactive SSH Output Redirection

Since ssh behaves like any other Linux command in terms of input and output, once we capture one of its streams, we can process it however we like.

4.1. Pipe SSH Output

As with other streams, we can pipe ssh output:

$ ssh [email protected] 'ip address' | grep global
inet brd scope global eth0

Here, we get the remote machine’s network information via ip. Subsequently, we pipe this to grep (Global Regular Expression Print) for filtering out only the global IP.

Of course, we can achieve this effect without direct pipes.

4.2. SSH in a Subshell

Indeed, we can use a subshell to get the data returned by SSH:

$ REMOTE_HOSTNAME="$(ssh [email protected] 'hostname')"
PING ( 56(84) bytes of data.
64 bytes from ( icmp_seq=1 ttl=666 time=66.6 ms

We first store the remote hostname in the REMOTE_HOSTNAME variable. After that, we use the ping command with the hostname as its argument.

Of course, these solutions are rarely useful without filtering for isolated pieces of data in an interactive ssh environment.

5. Interactive SSH Output Redirection

Since the complete output from an SSH session is available for piping only after the ssh client terminates, we must come up with a solution to get current data from interactive sessions immediately.

5.1. Stream Duplication

One way to get data from stdout without full redirection is the tee command:

$ echo '-----' > stdout.txt
$ ssh [email protected] | tee stdout.txt
$ hostname
$ exit
$ cat stdout.txt
$ hostname
$ exit

First, we create a file stdout.txt and populate it with five dashes. After that, we start an SSH session, piping to tee. Note how tee redirects all of the information within the SSH session simultaneously to stdout and stdout.txt.

Of course, the problem here is the verbosity and lack of filters. Next, we’ll check some more granular approaches.

5.2. Netcat

Another way to extract information from a live SSH session is just to send it out. We can use nc (Netcat) for transferring information from the session back to the client. For this, we need first to start a separate server on the client itself:

$ nc -l -p 36661

The -l flag starts a listening server at the port following -p. After that, in a separate terminal, we establish a reverse SSH tunnel session:

$ ssh [email protected] -R localhost:36660:localhost:36661

We read the -R (reverse tunnel) flag argument as follows: redirect any data to port 36660 of the remote host to the current client machine at port 36661. This allows us to send data via nc on the SSH server to the nc server we opened on the client:

$ echo "$(date)" | nc localhost 36660

Here, we send the current date to port 36660 of localhost, which is the SSH server. However, this information is actually transmitted to port 36661 of the client because of the reverse tunnel.

Indeed, going back to the client terminal with our nc server, we can see the current date just below the Netcat command. Broadly speaking, this process just establishes a reverse connection to the client, which the server uses to provide data back.

There are alternatives to nc for achieving the same. Furthermore, the other options we’ll discuss provide a valuable bonus feature: clipboard access.

6. SSH Clipboard

The SSH protocol standard does not specify a clipboard mechanism. However, we can often use every available option for copying and pasting that we have available locally.

For example, we could just select, copy and paste text from the GUI terminal window, where the SSH session was started. Alternatively, we can employ one of the methods below.

6.1. X Selections

If we want to send to the clipboard via the command line, we can use the xsel or xclip commands:

$ ssh [email protected] 'hostname' | xsel --input
$ xsel --output

Basically, we pipe ssh output to the xsel command. Importantly, we won’t be able to use tools like xsel and xclip without X Server running locally.

On the other hand, remote X11 usage is possible via xclip only if we:

  • install and run X Server on the local machine
  • add or uncomment X11Forwarding yes to /etc/ssh/sshd_config

To employ xclip, we start the ssh client with the -X (X11 forwarding) flag:

$ ssh -X [email protected]
$ echo "$(date)" | xclip -i

After we use xclip to get the data input on the remote machine, we can use the output on the local one:

$ xclip -o
Sun 10 Oct 2021 10:00:00 AM EST

Importantly, this data is only available during the SSH session, not after.

6.2. Netcat Clipboard

Of course, we can use the Netcat solution from above, but piping to xsel:

$ nc -l -p 36661 | xsel --input

Any data we receive on the nc server goes directly to the clipboard, which we can restore via xsel on the client. However, there are other options, which combine all of this functionality in a specialized package.

6.3. Lemonade

One such alternative is the lemonade command – a single tool, which allows us to:

  • start a listener on the client
  • send data from the SSH session to the client
  • execute predefined actions on the server

In fact, we use this tool in much the same way as nc. First, we start the lemonade server in a terminal:

$ lemonade start

After this, in a separate terminal, we ssh to our server as we did previously. The only change is the reverse tunnel ports – both are 2489, the default for lemonade:

$ ssh [email protected] -R localhost:2489:localhost:2489

Finally, we use lemonade on the server to send data back to the client:

$ echo "$(date)" | lemonade copy

Importantly, using the copy command to lemonade, we move SSH session data directly to our local clipboard. We can then paste this data not only via the graphical interface but also the command line on the client:

$ lemonade paste
Sun 10 Oct 2021 10:00:00 AM EST

Note that the tool, like the others, should be installed on both server and client. Furthermore, lemonade has other useful features, such as opening a browser on the client, redirecting to a given URL.

6.4. Clippy

We can achieve all of the above with clippy. In addition, Clippy implements more security and the ability to start an SSH session directly with the tool. This eases the reverse tunnel configuration:

$ clippy ssh [email protected]
$ echo "$(date)" | clippy set

Similarly to the other methods, we get the data via the same tool on the client:

$ clippy get
Sun 10 Oct 2021 10:10:00 AM EST

Clippy also supports executing arbitrary commands on the desktop instead of just the command line, as SSH does.

7. Summary

In this tutorial, we discussed ways to get data back to the client after and during an SSH session to a server. We considered interactive and non-interactive scenarios. In the end, we also explored options to send data directly to the local clipboard.

In conclusion, there are multiple ways, some easier than others, to send data from server to client, even when it comes to the client’s clipboard.

Authors Bottom

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

Inline Feedbacks
View all comments
Comments are closed on this article!