Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

When all you have is a serial console (say via telnet through a terminal server), what methods can be used to transfer files in/out of a host?

Cut/paste works for the small/printable stuff and I've played with a combination of uuencode/uudecode (with gzip) handle the unprintable but it's all very limiting.

share|improve this question
    
Given some of the comments you've left about availability of utilities, it would help if you could name the platform and/or outline the environment you're in. Otherwise, you're going to get the stock Kermit/XMODEM/YMODEM/ZMODEMk via terminal answers... – Avery Payne Aug 12 '10 at 17:11
    
I spend most of my day behind Solaris box. So in those terms, if all you had was SUNCreq (or perhaps SUNWCuser) what would you the answer? – Stephen Paul Lesniewski Aug 12 '10 at 17:51
    
a mere 5 years late, :P Now you can accept my answer, because it was exactly what you wanted.... but likely don't need today. – TechZilla Jul 19 at 2:45

The serial console programs¹ you'll use on the other end of the connection will have some way to send a file to the remote side. How exactly you go about it depends on what resources you have available on the remote system.

I Have lrzsz or kermit on the Remote Side

The easiest case is if you have a solid binary file transfer program installed on the remote side such as lrzsz or kermit. This was once more common than today, but your particular system might still have one of these.

The serial console program you're using on the local side almost certainly has a way to do a Zmodem or Kermit upload, which lets you send whatever you need directly.

In the case of Zmodem, just type rz on the remote system, which sends out a special string that the local serial terminal should understand, causing it to pop up a file picker dialog.

Kermit is a simpler protocol, so you have to start the transfer manually in that case.

I Don't Have a Binary File Transfer Program, but I Do Have uuencode/base64

There are several advantages to using a proper binary file transfer program like lrzsz or kermit: efficiency, checksumming, automatic retries, aborted transfer resumption, multiple file transfer, etc., but these are luxuries. If you only need to send one file, or you're sending files rarely, you can get away with ASCII uploads.

Because terminal protocols interpret many of the byte values that occur in a binary data file, you can't send the file directly through the same connection; if you do, the terminal emulation code on either end will try to interpret some of the data, corrupting the data and likely confusing the terminal handling code as well.

You get around this by encoding the binary data into a safe subset of ASCII on the local side, then turning it back into raw binary data on the remote side. This is what the uuencode and base64 programs do, differing only in minor algorithm choices.

On the local system, you encode the file:²

$ uuencode -o sbf.uue some-binary-file.gz some-binary-file.gz

Then you type this command on the remote system, and send the file using the local serial console's "ASCII upload" feature:

$ cat | uudecode

When the file upload finishes, hit Ctrl-C to get out of cat. Now you have your decoded file on the remote system, as you wanted.

But I Have Many Files to Send, and Printable ASCII Transcoding Is a Pain!

It is not hard to bootstrap yourself up to a higher level of technology. If the remote system has a C compiler, you can use the prior technique to send the remote system a copy of the lrzsz source code. On the local side:

$ uuencode -o lrzsz.tgz.uue lrzsz-0.12.20.tar.gz lrzsz-0.12.20.tar.gz

Then on the remote system, type this via the serial console program:

$ cat | uudecode
^C
$ tar xvf lrzsz-0.12.20.tar.gz
...build lrzsz normally

After you start the first command, do an "ASCII upload" of the lrzsz.tgz.uue file to the remote system. The pipeline accepts the uuencoded data and decodes it to a binary tarball for you, which you can unpack and build.

But I Don't Have a C Compiler on the Remote System

If you don't even have a compiler on the remote system, you can cross-compile the rz (or whatever) program on the local system and send it to the remote system using the above technique.


Footnotes:

  1. minicom, picocom, PuTTY, VanDyke CRT...

  2. You have to give the input file name to this version of uuencode twice, once to name the source of the input data, and again to declare what the remote system should call the file when it decodes the data to an output file. You could conceivably want the remote system to have a different name for its output file.

    Your local version of uuencode may behave differently.

share|improve this answer
    
Fantastic, I was hoping this question had an answer mentioning kermit! +1 ;) – Tim Jun 15 '12 at 14:44

Maybe you should give minicom a try.

share|improve this answer
    
Doesn't this require something like 'sx' or 'sz' on the source host? – Stephen Paul Lesniewski Aug 11 '10 at 17:19
4  
Nope, minicom handles its own file xfers. sx,sy,sz and rx,ry,rz are separate programs, usually found in packages aptly named lszrz or something. Though I would suggest using sz and rz. Small, simple and it does what it does. Minicom is a whole terminal emulator. – reiche Aug 11 '10 at 17:34
3  
This answer is not correct. Minicom spawns lrzsz for file transfers. Minicom can not and does not handle it's own file transfers. – Jonathan Cline IEEE Sep 2 '11 at 17:50

Don't know if this would work if all you had was a serial console, but if you have network access at all, then you could use nc(1) to copy files using TCP/IP.

# WARNING: Depending on your setup, this could make your system unbootable
root@destination-box.local # nc -l 8675 | dd of=/dev/sda1
root@source-box.local # dd if=/dev/sdb1 | nc destination-box.local 8675

In the above example, I cloned sdb1 from a source box to sda1 of the destination box. My choice of 8675 for a TCP port number was arbitrary; you could use any port you have access to. And it doesn't have to be a device; it can be any file.

kevin@destination-box.local $ nc -l 12345 >> ~/.ssh/authorized_keys
kevin@source-box.local $ cat ~/.ssh/id_rsa.pub | nc destination-box.local 12345

In the second example, I copied my rsa public key(~/.ssh/id_rsa.pub) and added it to the authorized keys file for the target host.

share|improve this answer
4  
Might I suggest a big red warning sign above your first idea? Some lonely soul with the heart to learn might execute something like that in the hopes of copying just files, without reading the following paragraph first of course :) – reiche Aug 11 '10 at 17:36

I would use kermit, the grandparent of filetransfer programs. We used that already long before there was Linux.

share|improve this answer
    
ahh yes.. I remember doing that but in this case kermit isn't install on the source host. – Stephen Paul Lesniewski Aug 11 '10 at 17:21

Basically you have to use pre-internet methods to transfer over a serial tty, and you must have a way to receive the transfer on the other side. Obviously the best way to do this is by using ZMODEM, which means you need to have a tool like sz already on the receiving end. However this isn't always possible, for example, when the receiving target is a router without a network.

The only possible way to do this transfer is directly over the channel, using terminal safe ASCII, in pre-8-bit clean style. I'm going to use more modern tools, that I'd hope are installed on most systems.

Sender:

First we encode our file

base64 file.tar.gz > file.tar.gz.b64

Now make sure your com send-file command is, ascii-xfr, this was my connection command line

picocom -f n -p n -d 8 -b 115200  --send-cmd "ascii-xfr -snv" /dev/ttyS0

Normally we want ascii-xfr on the receiving side, but since we don't have it, that -n works around this by maintaining correct line endings.

Receiver:

Now that we've connected, go to the directory where you want the received file.

cd /tmp/
cat > file.tar.gz.b64

On picocom, I just CTRL+a+s, and enter the full path of the file I'm sending. Once the transfer completes, you'll need to CTRL+c to break that cat.

Now we decode the file,

base64 -d file.tar.gz.b64 > file.tar.gz

Do whatever you can to verify that file is IDENTICAL to the one you sent, because an ASCII transfer has no checksum protection. My receiving box had sha512sum, but any checksum command would suffice. Once you manually confirm the sums match, you can assume the transfer was successful!

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.