How to connect to a serial port as simple as using SSH?
Is there a way to connect to a serial terminal just as you would do with SSH? There must be a simpler way than tools such as Minicom, like this
$ serial /dev/ttyS0
I know I can
catthe output from
/dev/ttyS0but only one way communication is possible that way, from the port to the console. And
echoout to the port is just the same but the other way around, to the port.
How can I realize two way communication with a serial port the simplest possible way on Unix/Linux?
screenthe most useful program for serial communication since I use it for other things anyway. It's usually just
screen /dev/ttyS0 <speed>, although the default settings may be different for your device. It also allows you to pipe anything into the session by entering command mode and doing
exec !! <run some program that generates output>.
See also http://www.noah.org/wiki/Screen_notes#using_screen_as_a_serial_terminal and the manual page stty(1), I had to add extra options (e.g. parity) for it to work.
`screen` is awesome, but I don't think it it simpler than `minicom` :-)
@CiroSantilli刘晓波死六四事件法轮功 - Screen may be not simpler than Minicom but because I already use Screen, for me it is less complexity to do my serial stuff with Screen too eliminating the need for Minicom totally.
If you try to switch the tabs in your browser or your virtual desktops with ctrl-a-commands you begin to realise being a Screen addict! ;-D
The main reason why you need any program like
minicomto communicate over a serial port is that the port needs to be set up prior to initiating a connection. If it weren't set up appropriately, the
echocommands would not do for you what you might have expected. Notice that once you run a program like
minicom, the port is left with the settings that
minicomused. You can query the communication settings using the
sttyprogram like this:
stty < /dev/ttyS0
If you have done it right; after booting the computer and before running any other program like
minicom,the communication settings will be at their default settings. These are probably different than what you will need to make your connection. In this situation, sending the commands
echoto the port will either produce garbage or not work at all.
sttyagain after using
minicom, and you'll notice the settings are set to what the program was using.
Minimal serial communication
Basically, two things are needed to have two-way communication through a serial port: 1) configuring the serial port, and 2) opening the pseudo-tty read-write.
`picocom` also will let you connect to a serial port without reconfiguring it (`--noinit`) and will let you exit without restoring the serial port configuration (`--noreset` or use `Ctrl-A`/`Ctrl-Q` to quit `picocom`). I've found `picocom` to be much easier to use than `minicom`. For reasons I haven't figured out, minicom will sometime simply not send or receive data on a port that worked moments before or that picocom has no trouble with. It's probably some arcane configuration option, but whatever it is I can't figure it out (and this behavior has happened on more than one machine).
I found a way using a shell script here that put
catas a background process and a while loop that read the user input and
echoit out to the port. I modified it to be more general and it fitted my purpose perfectly.
#!/bin/sh # connect.sh # Usage: # $ connect.sh <device> <port speed> # Example: connect.sh /dev/ttyS0 9600 # Set up device stty -F $1 $2 # Let cat read the device $1 in the background cat $1 & # Capture PID of background process so it is possible to terminate it when done bgPid=$! # Read commands from user, send them to device $1 while read cmd do echo "$cmd" done > $1 # Terminate background read process kill $bgPid
Also, I've made a slightly modified version below which can also send Ctrl+C and Ctrl+Z.
@Fritz Nice find! So if I get this right, the background process would never be killed because $? doesn't seem to expand to anything right?
@ihatetoregister: Not quite correct. The background process is killed, but not for the reasons one might expect. `$?` expands to the exit code of the last non-background command (in this case `stty -F $1 $2`), so it expands to 0 when there was no error. Thus, the last line becomes `kill 0` which in turn seems to kill the current shell and all its children (it behaves differently in interactive shells I believe). For all the details see the following explanation: http://unix.stackexchange.com/questions/67532/what-does-kill-0-do-actually
Howerver, the real gotcha in your script is that the background process is *only* killed if you press Ctrl+D to end your script, because that ends the `while` loop cleanly. If you kill it with Ctrl+C or with the `kill` command, then the `cat` process stays alive. To fix that you would need to use the `trap` command to execute `kill $bgPid` when the shell exits, like my script down below does. Honestly, I wouldn't even mind if you just added my whole script to your post. I tried to do that, but the edit was rejected.
Could you please clarify where the connect comes in, as this is commented out in your answer
"tio" is a simple TTY terminal application which features a straightforward commandline interface to easily connect to TTY devices for basic input/output.
Typical use is without options. For example:
Which corresponds to the commonly used options:
tio --baudrate 115200 --databits 8 --flow none --stopbits 1 --parity none /dev/ttyS0
It comes with full shell auto completion support for all options.
This script is based on another answer, but sends everything over the serial port (except Ctrl+Q), not just single commands followed by Enter. This enables you to use Ctrl+C or Ctrl+Z on the remote host, and to use interactive "GUI" programs like aptitude or alsamixer. It can be quit by pressing Ctrl+Q.
Just put the following code into a file
/usr/local/bin/femtocom(or any other place in
$PATH) and do
chmod +x /usr/local/bin/femtocom.
From there on you can connect to any serial port like this for example:
femtocom /dev/ttyUSB0 57600
#!/bin/bash if [[ $# -lt 1 ]]; then echo "Usage:" echo " femtocom <serial-port> [ <speed> [ <stty-options> ... ] ]" echo " Example: $0 /dev/ttyS0 9600" echo " Press Ctrl+Q to quit" fi set -e # Exit when any command fails # Save settings of current terminal to restore later original_settings="$(stty -g)" # Kill background process and restore terminal when this shell exits trap 'set +e; kill "$bgPid"; stty "$original_settings"' EXIT # Remove serial port from parameter list, so only stty settings remain port="$1"; shift # Set up serial port, append all remaining parameters from command line stty -F "$port" raw -echo "[email protected]" # Set current terminal to pass through everything except Ctrl+Q # * "quit undef susp undef" will disable Ctrl+\ and Ctrl+Z handling # * "isig intr ^Q" will make Ctrl+Q send SIGINT to this script stty raw -echo isig intr ^Q quit undef susp undef echo "Connecting to $port. Press Ctrl+Q to exit." # Let cat read the serial port to the screen in the background # Capture PID of background process so it is possible to terminate it cat "$port" & bgPid=$! cat >"$port" # Redirect all keyboard input to serial port
Putty works well on Linux and offers some convenience, especially for serial communications. It has one drawback I haven't been able to directly solve: no copy-paste from the Putty window itself. The windows version has a lovely auto-copy to clipboard on highlight, right-click to paste behaviour (and there are excellent plugins for both chrome and firefox to enable the same behavior), but on Linux, no copy love AFAIK.
If the lack of copy is a problem (it is for me) then turn on logging in putty and open a standard terminal window and
# tail -f putty.logand bidirectional text is available for standard copypasta action.
I find that Putty under Linux doesn't paste "the clipboard" (what you copy with control-C), but it will insert "the primary selection" (what you have currently selected in some program) with middle-mouse. Likewise you can select characters in Putty's screen to define the primary selection. But if I want text from a Putty screen to transfer to some VM, I need it to be the clipboard, so I have to use an intermediary program to receive the text from the main selection and then copy it to the clipboard.