Is there any port monitoring tool to watch the packets written on the port? I especially want to check if my program written in Java works so I need some kind of tool to see if my little application is writing the messages to the port. How do I do this?
-
7Packets aren't written on the port. Characters are. It's not like Ethernet at all.– LawrenceCCommented Apr 30, 2011 at 18:33
-
2Similar questions from sibling SE sites: stackoverflow.com/q/940374/12892 and serverfault.com/q/112957/4276– Cristian CiupituCommented Feb 4, 2015 at 8:12
10 Answers
socat is a tool to connect (nearly) everything to (nearly) everything,
and tee can duplicate streams.
In your use case you could connect your serial port /dev/ttyS0
to a PTY /tmp/ttyV0
,
then point your application to the PTY,
and have socat tee
out Input and Output somewhere for you to observe.
Googling "socat serial port pty tee debug" will point you to several "standard procedure" examples, one being:
socat /dev/ttyS0,raw,echo=0 \
SYSTEM:'tee in.txt | socat - "PTY,link=/tmp/ttyV0,raw,echo=0,waitslave" | tee out.txt'
The files in.txt
and out.txt
will then contain the captured data.
Updated after comments:
- The
socat
syntax looks confusing at first, but in fact, it's just two nested statements.
A small price to pay to such a powerful, versatile tool. - If you need to set up your serial port, or send other ioctls, do so before calling socat, as socat cannot proxy them.
- The single-purpose-tool
interceptty
from 2006 has slightly simpler syntax, but can only intercept TTYs (while proxying ioctls), and is probably not in your package manager. (Most Linux distros never added it to their repos.)
-
@peterh-ReinstateMonica What do you need to proxy the ioctl calls for? If it's just changing the baudrate, try
stty -F /dev/ttyS0 19200
. Technically, it should be possible by intercepting the system call using LD_PRELOAD, same aspadsp
.– hackerb9Commented Mar 15, 2020 at 9:55 -
@alex-stragies: I like
socat
, but the syntax is just too cumbersome. For this simple problem, I found theinterceptty
solution posted below to be much simpler:interceptty /dev/ttyS0
is all you need to create a PTY called /tmp/interceptty that can then be used by any program as a serial port.– hackerb9Commented Mar 15, 2020 at 9:59 -
1@hackerb9 As of 03/2020,
interceptty
is not in debian package management, not eventesting
, so -for me and some others- not a viable solution for many situations. And the syntax is only cumbersome the first 5-8 times ;) Commented Mar 15, 2020 at 13:03 -
Fair enough. I also tend to stick with software that's been vetted by Debian. Interceptty, despite the author disappearing, seems to be well written. A simple
./configure && make && sudo make install
worked for me.– hackerb9Commented Mar 16, 2020 at 22:06
I don't think the serial driver has any tracing functionality that would allow you to watch packets. You can use strace
to observe all the reads and writes from your application:
strace -s9999 -o myapp.strace -eread,write,ioctl ./myapp
-
1
-
strace will tell you if it tried to send characters to the port, and what the kernel responded with when it tried. depending on your flow control settings characters may arrive at the disconnected TXD pin or may not.– JasenCommented Jun 28, 2018 at 5:19
-
-
This works, but is an overkill in the sense that it'll monitor accesses to all files instead of the single
/dev/tty*
we're interested in.– RuslanCommented Jan 14, 2020 at 9:31 -
This got me going in the direction I needed. I have a hardware widget with a serial interface that I can only find an ancient Windows-32 app to control, and I was looking to monitor all of it's traffic while running under wine to try and reverse-engineer it in hopes of making a new library. I found that adding the
-P
option limits strace to only my device, and I also needed-f
to watch the child/fork processes:strace -o wine.strace -f -s 9999 -x -P /dev/ttyUSB0 wine start 'c:/Program Files (x86)/mydir/myapp.exe'
– JustinBCommented Apr 30, 2020 at 17:45
I found projects called Linux Serial Sniffer, jpnevulator, and Moni(Edit: Updated Link). The first two look like they do exactly what you want. The last one calls itself a monitor, but it actually looks like a standard serial communication program.
-
1thanks for that !! i will give it a try. by the way i solved the issue from my java side. i was missing a \r, so that prevented my message from writing on to the port. thanks for that anyways!!– DeepakCommented Apr 30, 2011 at 18:24
-
4The «LInux Serial Sniffer» is buggy, it absolutely takes out incoming data, thus another application which is actually listen to serial see nothing. But, at least, the data that goes outside seems to go without problem.– Hi-AngelCommented Mar 31, 2015 at 11:12
-
3From the jpnevulator FAQ: "Jpnevulator was never built to sit in between the kernel and your application."– ShelvacuCommented Jun 12, 2017 at 2:14
-
2-1 because of 3 comments: LInux Serial Sniffer is buggy, then Jpnevulator was never built to sit in between kernel and app and finaly Moni is dead... This answer just point to 3 externals links and don't give a real solution. (3 fail on 3 link, left nothing!) Commented Sep 20, 2019 at 11:49
-
1I think, this could be deleted in favor of Alex Stragies's answer using
socat
where solution is located between serial port and application. Commented Sep 20, 2019 at 11:56
interceptty
does that job:
interceptty /dev/ttyACM0 /dev/ttyDUMMY
or, with a nice output format and with configuring the backend device, and with line buffering:
interceptty -s 'ispeed 19200 ospeed 19200' -l /dev/ttyACM0 /dev/ttyDUMMY | interceptty-nicedump
and then connect with your programme to /dev/ttyDUMMY
.
-
1@AlexStragies: I have it on my arch linux system. AUR page: aur.archlinux.org/packages/interceptty, copy of the sources: repo.j5lx.eu/archive/interceptty/interceptty-0.6.tar.gz Commented Apr 3, 2017 at 10:22
-
I had to download it (using
wget
since clicking on the.tar.gz
file seemed to corrupt it somehow), installgcc
andmake
, then run./configure
andmake install
. Does exactly what the OP and I want though. Commented May 31, 2017 at 23:18 -
1
-
Worked great on Debian GNU/Linux. Was able to intercept a Windows program (running in Wine) with a simple
ln -s /tmp/interceptty ~/.wine/dosdevices/com5
. Excellent answer.– hackerb9Commented Mar 15, 2020 at 9:33
This is the way I finally choose
Thanks to Gilles's answer!
strace -s 9999 -e read -ffp $(sed '/ttyUSB0/s/^.*proc.\([0-9]\+\).fd.*/\1/p;d' <(ls -l /proc/[1-9]*/fd/* 2>/dev/null)) |& perl -e '$|=1;my %qa=(a=>7,b=>10,e=>33,f=>14,n=>12,r=>15,t=>11);sub cnv { my $ch=$_[0];$ch=$qa{$1} if $ch=~/([abefnrt])/;return chr(oct($ch)); };while (<>) { /^read.\d+,\s+"(.*)",\s\d+.*$/ && do { $_=$1;s/\\(\d+|[abefnrt])/cnv($1)/eg;print; };};'
Sorry, I will explain...
#!/bin/bash
strace -s 9999 -e read -ffp $(
sed "/tty${1:-USB0}/s/^.*proc.\([0-9]\+\).fd.*/\1/p;d" <(
ls -l /proc/[1-9]*/fd/* 2>/dev/null
)
) 2>&1 |
perl -e '
$|=1;
my %qa=(a=>7,b=>10,e=>33,f=>14,n=>12,r=>15,t=>11);
sub cnv {
my $ch=$_[0];
$ch=$qa{$1} if $ch=~/([abefnrt])/;
return chr(oct($ch));
};
while (<>) {
/^read.\d+,\s+"(.*)",\s\d+.*$/ && do {
$_=$1;
s/\\(\d+|[abefnrt])/cnv($1)/eg;
print;
};
};
'
- I use
ls -l /proc/[0-9]*/fd/* | grep ttyUSB0
instead oflsof ttyUSB0
because I seen them sometime slow. - So strace will trace current program using
ttyUSB0
- Syntax:
tty${1:-USB0}
will permit, used as a script or function, to run them with serial device name as argument:ttySniff USB0
orttySniff S0
and so on. - Perl script will
unbackslash
strings logged bystrace -s 9999
. - You could replace
strace -e read
bystrace -e read,write
orstrace -e write
depending on your need.
Note: I run them by using syntax:
script -t ttySniff.log 2>ttySniff.tm -c "./ttySniff.sh USB0"
so I could replay the whole operation and trace timing executions.
-
There is no security consideration, about what could be comming by serial port! Commented Oct 29, 2019 at 17:35
-
Try this:
screen /dev/tty.usbserial-blahblah 9600
works for me.
-
29This opens the port and assumes control over it, so nothing else can use it. This does not "monitor" or "sniff" the traffic.– Ian MCommented Jan 23, 2015 at 7:12
minicom
is missing from the list of tools to monitor serial ports. Use it as for example to listen to arduino device:
minicom --device /dev/ttyACM0 --baud 9600
-
2OP wrote "monitor", but meant "sniffer" ( = is able to read traffic in transit), while minicom is a serial port "client", and as such is not an answer to this question. The answer below from mike made the same mistake, and the comment there explains the terminology problem as well. Commented Mar 17, 2019 at 21:03
Have a look at ttyUSBSpy. It is on alpha stage, but it works.
-
2It doesn't. It is written in python, and the code does import some
import pcopy
, which is even Google gave up to find.– Hi-AngelCommented Mar 31, 2015 at 10:43 -
2Software/Homepage looks abandoned. Is not in package managers. Commented Apr 16, 2017 at 16:28
There are many answers and approaches to this that each have different properties. A common one is using socat, like the answer Alex gave above that's also discussed in this blog post.
However, if you'd prefer creating a separate device that's just a read-only version of the original device like myself - say, so that you can open minicom on the read-only device and let other software interact with the read-write device normally - I just came up with the following that works nicely.
socat /dev/ttyUSB0,rawer SYSTEM:'tee >(socat - "PTY,link=/tmp/foobar-ro,rawer" >%-) | socat - "PTY,link=/tmp/foobar-rw,rawer,wait-slave"'
That's complicated, so I'll break it down a bit. Logically it's this:
socat /dev/ttyUSB3,rawer SYSTEM:'tee [READ-ONLY PTY] | [READ-WRITE PTY]'
And it works roughly like so:
- The first socat command sets up a bidirectional pipe between the first address (
/dev/ttyUSB0
) and second (theSYSTEM
command). - Inside the
SYSTEM
command now, tee duplicates its stdin (i.e. the output of/dev/ttyUSB0
) to both[READ-ONLY PTY]
and to its own stdout, which we then pipe to[READ-WRITE PTY]
. [READ-ONLY PTY]
is created with a 2nd socat command where the first address is-
(shorthand for socat'sSTDIO
address type) and the second is a new PTY. We also make sure to close this 2nd socat command's stdout with>%-
; this is what makes it read-only.- For a reason I don't quite understand, unless the 2nd socat's stdout is closed, tee seems to include the output from the process substitution in its own output. I'm not sure why tee would be reading from its arguments at all.
- Finally,
[READ-WRITE PTY]
is created with a 3rd socat command similar to the 2nd. This 3rd socat's stdout becomes the output of the SYSTEM address in the 1st socat and is fed to the original device's input, completing the loop.