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:
- generated
- copied to our remote server baeldung.com
- configured on both our local and remote machines
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
personal.local
$ ssh [email protected]
$ hostname
baeldung.com
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 baeldung.com, 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
personal.local
$ ssh [email protected] 'hostname'
baeldung.com
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 10.0.6.66/24 brd 10.0.6.255 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 "${REMOTE_HOSTNAME}"
PING baeldung.com (203.0.113.66) 56(84) bytes of data.
64 bytes from 203.0.113.66 (203.0.113.66): 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
baeldung.com
$ exit
$ cat stdout.txt
-----
$ hostname
baeldung.com
$ 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
baeldung.com
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.