Developed By:

Developed By:

Thursday, July 17, 2008

Avoid latency while editing remote files using bcvi

The ability to run both console and graphical programs securely on a remote system using SSH brings you a great deal of freedom. When the communications link to that remote system has high latency, however, running interactive programs such as a text editor on the remote machine can become a real test of your patience. The bcvi project lets you edit files on a remote system using gvim (or another editor) on your local desktop machine to avoid the latency. Even without latency issues, bcvi is a handy tool when you want to use gvim to edit a file on a server that does not have gvim or the X libraries installed.

bcvi works by creating a port-forwarding "back-channel" when you connect to a remote system with SSH. On the remote system, when you execute bcvi, it uses this back-channel to tell your desktop machine to start gvim and fetch the file you want to edit on the remote machine. This all relies on gvim supporting SSH URIs so it can download the file from the remote machine over SSH and put it back again once you are done editing.

There are no packages of bcvi for openSUSE, Fedora, or Ubuntu. The bcvi script is presented inline on its home page, and can also be downloaded. The bcvi script must be installed on both the client and server machines, which you can do with the following commands:

# cp /.../bcvi /usr/local/bin/
# chmod 755 /usr/local/bin/bcvi
# dos2unix /usr/local/bin/bcvi
# ls -lh /usr/local/bin/bcvi
-rwxr-xr-x 1 root root 8.2K 2008-06-23 14:59 /usr/local/bin/bcvi*

The same bcvi script is used in three contexts: a daemon process that invokes gvim on your desktop machine in response to editing requests that you start on remote hosts; to wrap the invocation of SSH, setting up additional port forwarding so bcvi on the remote system can talk to the bcvi daemon process on your desktop machine; and on remote systems to initiate an edit request on your desktop machine.

When you SSH into a remote machine with bcvi the TERM environment variable has additional information added to it so bcvi on the remote machine can work out how to talk to your desktop machine. On the remote machine you will most likely want to add the following two lines to your shell's ~/.profile file. The first line lets bcvi take its information out of the TERM environment variable, leaving TERM the way it would normally be set. The second line makes typing vi on the remote machine execute bcvi, which will open gvim on your local machine. On most Linux systems, bash is the default shell, so the file to edit is ~/.bash_profile.

test -n "$(which bcvi)" && eval "$(bcvi --unpack-term)"
alias vi=bcvi

You also need to ensure that bcvi is running as a daemon on your desktop machine so that when you execute bcvi on the remote machine it can communicate with the local bcvi daemon to open the file for editing. You can start the daemon automatically by adding the following line to your ~/.bash_profile:

bcvi -l &

Instead of having to remember to wrap your SSH invocations with bcvi, you can use a shell alias on your desktop machine to wrap all connections, as in the code below. I found that if I added the alias to ~/.bash_profile instead of ~/.bashrc it did not take effect when logging in to a local X window session -- so although adding the code to the .bashrc means it is executed every time you create a shell, you are guaranteed that the alias will be in effect all the time.

alias ssh="bcvi --wrap-ssh --"

With these modifications to the .bash_profile file on your desktop machine and the servers you are connecting to, you can edit files as shown below. Because you have set up vi as a shell alias to bcvi, you don't have to change your command line at all in order to edit a file on the remote system with gvim on your desktop machine. The screenshot includes this interaction, where I have also saved the file and executed cat on the remote machine to verify that the updates were saved.

[ben@virtual_client ~]$ ssh ben@virtual_server
[ben@virtual_server ~]$ date >bcvi-test-file.txt
[ben@virtual_server ~]$ vi bcvi-test-file.txt

You can use a text editor other than gvim with bcvi as long as the text editor you want to use can load and save files over SSH. For instance, the gedit text editor can load and save over SSH:// URIs. To allow bcvi to edit using gedit, you need to add the following procedure to the bcvi Perl script, perhaps just after the execute_vi function.

sub execute_gedit {
my($self, $alias, @files) = @_;

s{^}{ssh://$alias/} foreach @files;

system('gedit', '--', @files);

With the above new function in bcvi, you can execute the following command on the remote host to have gedit run on your desktop machine and load the specified file. If you like this, you can add the gedit alias to the ~/.bashrc file on the remote host to allow such editing without having to remember to change the command line.

bcvi --command gedit bcvi-test-file.txt
alias gedit="bcvi --command gedit"

If you use bcvi to connect to a machine but do not include the bcvi --unpack-term command in the startup files for the remove shell (~/.bash_profile as shown above) then you will get an annoying debug message when you exit your SSH connection, as shown below:

$ ssh root@virtual_server
Last login: Mon Jun 23 15:16:13 2008 from virtual_client
[root@virtual_server ~]#
[root@virtual_server ~]# exit
BCVI_CONF=virtual_server:localhost:5009': unknown terminal type.
Connection to virtual_server closed.

bcvi is a handy tool to know about if you maintain a system over a high-latency network link. If the file you are editing is only a few kilobytes large but the round-trip latency makes even moving the cursor painfully slow, bcvi should make for a quicker, frustration-free edit.