VirtualBox lets you share the clipboard between your host and your guests, but it’s an on or off setting. If you’re using your VMs for any kind of sandboxing, you probably leave that setting disabled so that the VMs don’t get blanket access to your host’s clipboard.
Of course, you can turn it on, copy and paste what you needed, then turn it off again. But, if you’re like me, you’ll forget to turn it off!
We can do better, and sync the clipboard on demand with a specific VM, using “vboxmanage
” and “xsel
“, a CLI utility that lets you manipulate a desktop’s clipboard.
Read and write the clipboard with xsel
To set the clipboard, pipe any text into “xsel -b
“:
echo "foo" |xsel -b
For example, you can copy the content of a file:
cat myfile.txt |xsel -b
To get the clipboard, just call “xsel -b
“:
xsel -b
Use xsel to get or set a VM’s clipboard
We can combine these “xsel
” operations with what we learnt in my previous article: “VirtualBox: executing commands inside a VM with vboxmanage”. We’ll use VirtualBox’s “vboxmanage guestcontrol
” command on the host, to execute “xsel
” on the guest.
For this to work, you’ll need “xsel
” on both the host and the guest! A simple “dnf install xsel
” or “apt install xsel
” should be enough to install it if it’s not on your system yet.
Here’s the most basic version, but we’ll improve it further down in this post:
CLIPBOARD_DATA=$(xsel -b)
vboxmanage guestcontrol "VM_NAME" \
--username "VM_USER" --password "VM_PASSWORD" \
run --putenv DISPLAY=:0 -- "/bin/bash" "-c" \
"echo -n \"${CLIPBOARD_DATA}\" |xsel -b"
The first line gets the content of the clipboard and puts it in the “CLIPBOARD_DATA
” variable. That’s the content we need to send to the guest.
Lines 3 through 6 specify the “vboxmanage guestcontrol
” command used to execute things on the guest. I’ll refer you one last time to my previous article on the subject if you want to learn more about it.
Only lines 5-6 are really interesting:
run --putenv DISPLAY=:0 -- "/bin/bash" "-c" \
"echo -n \"${CLIPBOARD_DATA}\" |xsel -b"
We need to specify which display we want to interact with (“--putenv DISPLAY=:0
“), even though xsel is a CLI utility. That’s because the clipboard is a X feature (a “desktop” feature).
Then we execute "echo -n \"${CLIPBOARD_DATA}\" |xsel -b"
in bash in the guest. Notice how I enclosed that part in double quotes: that’s because I want ${CLIPBOARD_DATA}
to expand on the host (that variable doesn’t exist in the guest).
We pipe the content of the variable into “xsel
-b”, thus setting the guest’s clipboard.
Use base64 to avoid issues
As we just saw, “${CLIPBOARD_DATA}
” expands on the host, so we’ll run into problems if the variable contains characters such as quotes, that will mangle the command. An easy solution is to encode the clipboard data to base64
, and of course decode it (“base64 -d
“) on the guest:
CLIPBOARD_DATA=$(xsel -b |base64)
vboxmanage guestcontrol "VM_NAME" \
--username "VM_USER" --password "VM_PASSWORD" \
run --putenv DISPLAY=:0 -- "/bin/bash" "-c" \
"echo -n \"${CLIPBOARD_DATA}\" |base64 -d |xsel -b"
You’ll notice the guest will send you its previous clipboard value, and that is supposedly explained by this paragraph in the manual page:
By default, this program outputs the selection without modification if both standard input and standard output are terminals (ttys). Otherwise, the current selection is output
(man xsel)
if standard output is not a terminal (tty), and the selection is set from standard input if standard input is not a terminal (tty). If any input or output options are given
then the program behaves only in the requested mode.
That’s a bit convoluted to read (for me, at least!), but it seems to be fixed if we explicitly tell xsel
to read from standard input, by adding the “-i
” option. We’ll explicitly do the same when outputting to standard output with “-o
“.
The final commands
So here’s our final version, as a nice little script:
#!/bin/env bash
# Copies the host's clipboard to the VM's clipboard
CLIPBOARD_DATA=$(xsel -ob |base64)
vboxmanage guestcontrol "VM_NAME" \
--username "VM_USER" --password "VM_PASSWORD" \
run --putenv DISPLAY=:0 -- "/bin/bash" "-c" \
"echo -n \"${CLIPBOARD_DATA}\" |base64 -d |xsel -ib"
And here’s the script that does the opposite, i.e. gets the VM’s clipboard and puts it in the host’s:
#!/bin/env bash
# Copies the VM's clipboard to the host's
CLIPBOARD_DATA=$(vboxmanage guestcontrol "VM_NAME" \
--username "VM_USER" --password "VM_PASSWORD" \
run --putenv DISPLAY=:0 -- "/bin/bash" "-c" \
"/usr/bin/xsel -ob | /bin/base64")
echo -n "${CLIPBOARD_DATA}" | base64 -d | /usr/bin/xsel -ib
Remember to replace “VM_NAME
“, “VM_USER
” and “VM_PASSWORD
” with the appropriate values for your setup!
Conclusion
Using these scripts, you can get and set the VM’s clipboard even while leaving the clipboards sharing feature off. You can now be assured that the VM will get the clipboard’s content only when you intend it to.
Also, xsel
is a great utility, that can be used in local scripts for streamlining any workflow involving the clipboard!
Do you have any comment, question or suggestion? Leave a reply below or checkout my contact details at the bottom of the page.
Leave a Reply