Serial Port Console Log
by Pete R. Jemian, UNICAT
last updated: 26 June 1998
For questions about this URL, send mail to jemian@anl.gov
Table of Contents
Description
Some computer systems provide diagnostic output on a dedicated console
(RS-232) port. When used in an embedded system, these computers often
do not have a display to show these messages. It is sometimes desirable
to log any information from these console ports to a file for later examination.
The serial port console log script was designed to record ASCII text
input from a serial port on a UNIX workstation. It has been tested
on SunOS 4.1.4, Solaris 2.5.1, Linux Slackware v2, and RedHat Linux v5.0.
The input is (presumably) from a console port of some other computer (such
as VxWorks) connected via an RS-232 connection.
The script can be run either as a foreground or background task and
writes its output to stdout.
Requirements
These scripts were designed to run only on a UNIX workstation.
Access to the serial ports of a UNIX workstation is often restricted
to the root account. You will probably need to assign the
read/write permission to the serial ports to make effective use of these
scripts. For example, have your system administrator issue the command:
unix prompt> chmod 666 /dev/ttya
Also, you'll need the expect language which relies on having
the Tcl language installed. See below for these details.
Check the expect home page (see below) to see if the most recent
version is compatible with Tcl 8 yet. Otherwise, you'll
need Tcl v7.6.
Installation
Be sure that you have met all the system requirements above. Especially,
make sure you have expect installed (this means you will also
have Tcl installed).
Copy the source code below (using cut and paste from your WWW browser)
into a directory on your executable path. Name the file serialWatch.exp.
Give the file executable permissions with the UNIX command.
unix prompt> chmod +x serialWatch.exp
As long as you execute serialWatch.exp from a directory where
expect is on the executable path, then the first four lines should
automagically find expect and start the console port logger.
Otherwise, remove the first four lines of the script (script should begin
with "#!/usr/local..." line) and replace "/usr/local/bin/expect"
with the full path to the expect executable.
If you wish to log serial port data to a common directory (such as shown
in example 3 below) then you'll need to create that directory, as well.
To change the serial port parameters, you'll need to edit the script
a little more. Look at the line that reads "set baud 9600"
and the few lines afterward. Consult the UNIX man page for
"stty" and make proper adjustments.
Serial Port Console Log Script source code (written
in Expect)
Here is the complete expect script necessary to log text that comes in
on one of the serial ports. It assumes that the text is terminated
by a new line (\n) character for each line. Each line is
then time-stamped and written out to a file.
#! /bin/sh
# the next line restarts using expect \
exec expect $0 ${1+"$@"}
#!/usr/local/bin/expect -f
#
# serialWatch.exp
# Connect up to a device on a serial
port
# Time stamp any incoming lines to stdout
# port is any
serial port (omit the /dev/ prefix)
# e.g. ttya,
cua0, serialA, serialB, boca01 - boca16
if {$argc != 1} {
puts "$argc, $argv"
puts "usage: serial.exp port"
exit
}
proc timeStamp {} {
global tcl_version
if {$tcl_version >= 7.5} {
# "clock" command requires Tcl
v7.5 or greater
# internal routine a little faster
than making a system call
set stamp [clock format [clock
seconds] -format %Y-%m-%d,%T]
} else {
# fall back to standard UNIX system
call
set stamp [exec /bin/date +%Y-%m-%d,%T]
}
return $stamp
}
puts "\n[timeStamp] Log starting..."
set port /dev/$argv
set spawned [spawn -open [open $port w+]]
puts "[timeStamp]: [string trim $spawned \r\n]"
set baud 9600
# -parenb means don't use a parity
bit
# -cstopb means "not 2 stop bits,
but 1"
# cs8 means 8 bits
# -echo means no echo (full duplex?)
stty ispeed $baud ospeed $baud raw -echo cs8 -parenb
-cstopb onlcr < $port
log_user 0
# log each input line
# add a timeStamp at the beginning of each
line
while {1} {
expect "\n" {
puts "[timeStamp]: [string trim
$expect_out(buffer) \r\n]"
}
}
Examples
1 Simple example
Here is an example script to start logging a serial port. Output
will appear on stdout (usually your screen).
unix prompt> serialWatch.exp ttya
You should see output that looks like
1998-06-26,11:51:15 Log starting...
spawn [open ...]
1998-06-26,11:51:15: 0
As more information comes in, you will see lines that look like
1998-06-22,13:26:35: ldpp < bin/hideosLib
1998-06-22,13:26:39: value = 7467180 = 0x71f0ac
1998-06-22,13:26:39: #bpLoad 1, "bin/xfd_app"
1998-06-22,13:26:39: hideos_main
1998-06-22,13:26:39: Hideos welcomes you
1998-06-22,13:26:39: hideosDebug=005d0aec
Each line is time-stamped and has the complete information received
since the previous \n character.
You can stop this simple example by typing Control-C (^C).
2 Directing output to a file
Continuing from example 1, stdout can be redirected to a file
and the logger will be run in the background.
unix prompt> serialWatch.exp ttya >>& ttya.log
&
[1] 15268
The process ID number (PID) of the background process is 15268.
Stopping this example is a bit more difficult. First you must
find out the UNIX process ID number (pid), then kill the process. Here's
how that would look.
unix prompt> ps
PID TTY STAT TIME COMMAND
12466 p0 S 0:00
-tcsh
15131 p0 R 0:00
ps
24267 ? S
0:00 expect /usr/local/unicat/bin/serialWatch.exp ttya
unix prompt> kill 24267
3 UNICAT VxWorks Console Logs
Here is another example script to start logging several serial ports.
In this case, the serial ports are named /dev/boca01, /dev/boca02,
... /dev/boca16. These ports have been added to a Linux-based
PC using the BocaBoard BB2016 16-port serial expander. The output
goes into a specific subdirectory. The data coming in on the serial
ports are from the console ports of several VxWorks computers. This
is a script I call start-logs, which has UNIX permissions of 775.
#!/bin/csh
#
# start-logs
setenv BIN /usr/local/unicat/bin
setenv LOG /usr/local/unicat/logs/serial
$BIN/serialWatch.exp boca01 >>& $LOG/bwi_vxworks.log
&
$BIN/serialWatch.exp boca02 >>& $LOG/iad_vxworks.log
&
$BIN/serialWatch.exp boca05 >>& $LOG/jfk_vxworks.log
&
$BIN/serialWatch.exp boca07 >>& $LOG/sfo_vxworks.log
&
$BIN/serialWatch.exp boca08 >>& $LOG/lax_vxworks.log
&
#$BIN/serialWatch.exp boca04 >>& $LOG/iad_aim.log
&
#$BIN/serialWatch.exp boca06 >>& $LOG/jfk_aim.log
&
Stopping this example is very much the same as for example 2.
First find the PIDs for the processes and then kill each PID.
unix prompt> ps
PID TTY STAT TIME COMMAND
12466 p0 S 0:00
-tcsh
15131 p0 R 0:00
ps
31198 ? S
0:00 expect /usr/local/unicat/bin/serialWatch.exp boca01
31199 ? S
0:00 expect /usr/local/unicat/bin/serialWatch.exp boca02
31200 ? S
0:00 expect /usr/local/unicat/bin/serialWatch.exp boca05
31201 ? S
0:00 expect /usr/local/unicat/bin/serialWatch.exp boca07
31202 ? S
0:00 expect /usr/local/unicat/bin/serialWatch.exp boca08
unix prompt> kill 31198 31199 31200 31201 31202
To-do
-
Devise a better way to stop processes running in the background.
The drawback to doing this is that what works now is not all that bad.
-
Set a timeout on incomplete lines of incoming data so that devices which
don't send a trailing \n (such as "\nThis is
my next text string") can be logged in the file in a more timely
fashion.
-
Port these scripts to other machines such as WinXX. Contingent on expect
running on that platform.
-
Make configuring serial port parameters easier. As-written, the script
only handles one serial port configuration.
-
Check compatibility with Tcl v8. Is expect up to date?
Other links
Here are some links to other interesting sites that may be related to this
page.
For questions about this URL, send mail to jemian@anl.gov
|