I do a lot of work with network devices, which are often headless and require the use of serial consoles for out-of-band access. My go-to on MacOS and Linux has been screen, but various little issues over the years have led me to consider other options. I tried minicom on the recommendation of a colleague, but that didn’t work for me either.
I’ve struggled to pinpoint my problem with the aforementioned tools; I think I just want something less featurful, something that literally only gives me a tty via serial and doesn’t have anything unnecessary between my terminal and the remote shell. Over the weekend, I randomly happened upon an article about using socat for serial on Hacker News, and thought it might be just what I have been searching for. So I tried out the example and it failed miserably with the socat from Homebrew (MacOS being the OS on my daily driver).
I took the example command from the article and made the minimal changes for my environment (the name of my adapter’s serial device), but right off the bat I got an error:
> socat -,rawer,escape=0x0f /dev/tty.usbserial-AI066OQC,b115200,rawer
2020/05/20 22:25:06 socat[72638] E parseopts(): unknown option "b115200"
A quick google search turned up a number similar reports, and led me toward
the ispeed
and ospeed
options. Reviewing the manpage for these parameters
also suggests that the b
option is not available on all operating systems,
MacOS presumably among those. The manpage also explains these are used to set
the baud rates for incoming and outgoing data on the line, respectively (anyone
ever run into asymmetric serial speeds in the wild?). Anyway, that’s an easy change:
> socat -,rawer,escape=0x0f /dev/tty.usbserial-AI066OQC,ispeed=115200,ospeed=115200,rawer
# and nothing at all happens, nor does the ctrl+o escape work
# eventually I had to resort to a kill -9 in another window
Bummer. I guess it’s not so easy after all.
After far too long playing with permutations of options and searching the ends of the internet for suggestions, I finally found the magic incantation (with some hints from the sample command in this stack overflow question)
> socat -,rawer,escape=0x0f /dev/tty.usbserial-AI066OQC,clocal=1,nonblock=1,ispeed=115200,ospeed=115200
I am really excited about this new way to connect via serial. If nothing else, ctrl+a goes to the beginning of the line with no other escape sequence, and I am not at the mercy of any scrollback buffer beyond that of iterm. Alone, those are two killer features and make it so a serial connection really isn’t any different than any other terminal session I use throughout the day (besides perhaps speed).
That said, the above solution isn’t very pretty. But we can wrap it up as a shell function to make it easier to use:
# socat-serial => social
social() {
local DEV=${1?must specify the serial device}; shift
local BAUD=${1:-9600}
socat -,rawer,escape=0x0f ${DEV},clocal=1,nonblock=1,ispeed=${BAUD},ospeed=${BAUD}
}
# now you can invoke like
> social /dev/tty.usbserial-AI066OQC 115200
Drop that in your .bashrc or equivalent and off you go. Kill the connection with ctrl+o per the escape code.
I don’t have a need for more options, but ixon/ixoff
turn flow
control on and off, respectively, and csX
where `X is number of bit can change the
length of chars as needed. I am sure it supports other obscure parameters too; check the
manpage. For heavy-duty uses a function alone might not suffice. I could totally see this
evolving into a whole wapper script around socat, where needed.
Happy console-ing!