Get two Linux (virtual) boxes talking over a serial port - linux

What is the best way to setup one Linux box to listen on its serial port for incoming connections? I've done a lot of googling but I can't find the right combination of commands to actually get them to talk!
My main objective is to provide a serial interface to running instances of kvm/qemu VMs. They currently only have a VNC interface (they are on headless servers, no X). I can get the VM to create a serial device by starting it with the -serial file: flag, but how to talk to it, is a whole other problem. Both boxes are running Ubuntu 8.04.

The Linux Serial HOWTO has a lot of detailed information about serial communication in general. The more-specific Linux Remote Serial Console HOWTO is what you're really looking for if you want to be able to log into your virtualized systems using the serial port as if you were at the console. As Hein indicated, you'll need a null modem cable and need to run minicom on the remote terminal.
The Linux console is used in two ways, each of which must be configured separately for serial use. You can configure the kernel to copy its messages over the serial port, which is occasionally interesting for watching the system boot and nearly indispensable if you're doing kernel debugging. (This requires kernel support and updating the boot parameters so the kernel knows you want serial output; see chapter 5 of the second howto.) You're probably more interested in logging in via the serial port, which requires running getty on the serial port after boot (just like your system already runs getty on the virtual terminals after boot), which is described in detail in chapter 6 of the howto.

I assume you connect the two serial ports using a "null modem" cable.
Use a program like minicom to talk to remote system -- you probably need to set up the communication parameters and possibly turn off hardware flow control (if your cable doesn't have the flow-control lines connected).

Say you're doing this on /dev/tty1.
in the shell
chown *youruser* /dev/tty1
then in a Perl script called example.pl
open PORT, "</dev/tty1" || die "Can't open port: $!";
while (defined ($_ = <PORT>))
{
do_something($_);
}
close PORT;
Obviously there is more to do if you want this to start automatically, and respawn on error, and so on. But the basic idea is to read from the serial port like a file.

Related

Using gdbserver on remote device w/ a single serial connection?

I'm debugging an embedded application that runs in a Linux environment on a remote target. The only usable interface to the board is a single serial interface. Right now that's hooked up /bin/sh on init. I'm connecting with minicom, (re-)loading my application with lrzsz, and using printfs to get the job done.
I'd like to use gdbserver for more fine-grained debugging, but connectivity seems like a problem. Normally I'd connect over ethernet, but that's not available on this hardware. I understand gdbserver can run on a serial line, but right now my one comm port belongs to the shell.
Is there a good way to work around this restriction? Ideally I'd like to be able to run gdbserver and get back to a shell when I'm finished. I've tried starting gdbserver from the shell using the one available serial interface (/dev/ttyS0), then quitting minicom and starting GDB on my host, but it's messy & doesn't appear to work (even after setting remotebaud appropriately). Should that work? What's the sane thing to do in this situation?
How about the old-school solution? Use PPP to run IP networking over your serial line. You can then ssh (or even telnet) to your board, and connect to gdb at the same time. Given your circumstance, I'd recommend starting pppd manually to reduce the risk of locking yourself out through misconfiguration. The LDP link dates from 2000, but contains a lot of debugging advice.

How to attach ttyS to screen and capture it simultaneously

For capturing ssh sessions I use "script" command: "script -c 'ssh user#host' outfile". But I have no idea how to capture sessions to remote hosts, that connected over com(serial) port.
screen script -c 'screen /dev/ttyS0 57600' file
ends immediately with empty log. Both 2 functions that implemented in screen is necessary: ability to switch between opened sessions and ability to perform i/o to /dev/ttyS. I started develop some tiny utility to redirect stdin/stdout to /dev/ttyS but now it's so buggy and doesn't work yet.
First off, a terminal program, like minicom (or good-ol cu), as suggested by Laszlo, is needed to communicate with the remote system. Once you can get such a program to work, then screen can be brought into the picture. Note that this also requires a getty running on the remote computer's serial port. If it's an old-fashioned serial port, you may also need a special null-modem cable.
Screen can be used with such a connection to be able to move access of the session across terminals. However, it cannot be used to spawn more than one session with the remote server. That's because the program running on the serial port (getty) only supports a single session. In this case, the screen runs on the local machine, and the terminal-program session running within screen connects to the remote server. So, it is possible to have multiple screens, but just not more than one connected to the remote server over a single serial port.
With all of that said, serial ports can be used to network two machines, assuming both support the same serial-line networking protocol. Networking eliminates these restrictions.
To open an interactive terminal session to a COM port (/dev/ttyS*), you probably want to use a terminal emulator software, like 'minicom'.

In Linux, how to occupy console the std out exclusively?

I am working on embedded Linux, only one serial port, and used to be debug console. However, I need to I/O data by serial port, too. How can I use the console, the serial port, exclusively?
Remove the appropriate argument from the kernel command line and disable any getty that may be started on it by the startup processes.

embedded linux, how to switch the use of the serial port at the push of a button?

I am a business programmer with a few years of Linux administration experience. I'm starting out in embedded Linux. Yesterday, we were discussing a new device design and I was asked a few questions I had no answers for.
The engineers want to have some push buttons on an electronic board with a serial port on it. The OS is Linux.
Normally, when a user will connect to the serial port, a protocol will answer him instead of a Linux login prompt. However, if he pushes a sequence of buttons on the device, a Linux prompt will answer him on the serial port instead.
The Linux driver to handle the push button interrupt handling aside, how can you switch the basic use of the serial port like that? Does anyone have a URL reference on how to do this? (preferably with some sample code)
Note: I proposed providing a nice menu on login for a given user, but no can do.
Thanks in advice for any suggestions.
Best regards,
Bert
The main problem is that the process that implements your device protocol is probably keeping the serial port open.
In this case you should probably:
Wait for the button event
Have the protocol process close the serial port - terminating that process completely might also do for you
Launch a *getty process - or whatever your embedded target uses to present a login prompt on the serial port
Restore the protocol process once you are done
EDIT:
In the steps above I assume the more common case where the process that controls the serial port (e.g. pppd) is not able to act as a getty substitute to provide a login prompt. It is also typically not the same process that provides telnet/SSH/whatever logins.
That said, it's quite possible on a customised embedded Linux system for a process to do more than one thing. In that case you have to configure or modify that process to switch operational modes when appropriate.
Without more information about your embedded target it's impossible to provide a more specific answer.
The getty process is usually started on serial ports to provide a login prompt by /sbin/init, which is configured in /etc/inittab.
init has the concept of "runlevels". Each runlevel defines a separate set of processes that init will keep running. One elegant way to implement this would be to design your "protocol" process so that it is started by init, in the same way as getty. You can then tell init to run your process in some runlevels, and getty in others, and have the pushbutton switch between runlevels. For example, your /etc/inittab might include:
T0:2:respawn:/sbin/getty -L ttyS0 9600 vt100
P0:345:respawn:/sbin/protocol ttyS0 9600
This will run your protocol command on the first serial port in runlevels 3, 4 and 5; but getty in runlevel 2.

Software serial port loopback on linux

Currently I need to develop some program that will communicate with cisco devices over serial line. I want to build testing environment on my development linux machine. So, I found dynamips cisco emulator. This emulator can provide interface via serial line with '-U /dev/ttyS0' option. Well, this causes dynamips to open hardware serial port and communicate via it. I'm able to connect to this hardware serial port from another linux machine with serial client like minicom.
However, since i'm using virtualbox for both linux machines, I link serial ports via virtualbox ability to forward serial port to named pipe. This scheme seems to be working, but very redunant. I'm looking for a method to run dynamips and minicom on a single linux machine.
I found that pseudo-terminals could be useful in my case. But I've tried to run dynamips with '-U /dev/ptmx' and then connect with minicom to created /dev/pts/... port and vice versa. In both cases I've got input/output error on both sides.
Unfortunately, modern pseudo-terminals aren't that easy. After opening the master with posix_openpt() or open("/dev/ptmx"), you must call grantpt() and unlockpt() on the master FD before it and its corresponding slave device are usable. (The openpty() etc. utility functions simplify this.)
As a workaround, the ever handy socat may be of use.
# terminal 1
socat pty:link=$PWD/pts unix-l:$PWD/ptm-pipe &
dynamips -U $PWD/pts
# terminal 2
socat unix:$PWD/ptm-pipe -

Resources