pio device monitor が Operation not supported by device で落ちる
初出: 2026-05-19
症状
非対話シェル(スクリプトから呼んだとき、subprocess 経由、CI 環境 など)で:
bash
pio device monitor --port /dev/cu.usbmodem83301 --baud 115200を実行すると:
termios.error: (19, 'Operation not supported by device')で落ちる。
原因(噛み砕き)
- PlatformIO の monitor は中で
pyserialのminitermを使っている minitermは 「キーボード入力を1文字ずつ捕まえてマイコンに送る」 ためにターミナルを raw モードに切り替える- raw モードへの切り替えは
termios.tcgetattr()という UNIX のシステムコールが必要 - このシステムコールは 本物の TTY(仮想端末)が割り当てられていないと失敗する
- 普通にターミナルから打つときは TTY があるので問題ないが、スクリプトの中から
subprocess.run(...)で呼ぶ とか バックグラウンドプロセスとして起動する とき TTY が無いので死ぬ
要するに 「PlatformIO monitor は対話的に使う前提のツールで、自動化からは呼べない」。
対処
A. 普段の開発: そのままターミナルで実行する(推奨)
何も問題ない。
bash
pio device monitorB. 起動直後のログだけサクッと取りたい
pyserial で直接読む小さなスクリプトを書く:
python
# scripts/serial-snapshot.py
import serial, time, sys
port = sys.argv[1] if len(sys.argv) > 1 else '/dev/cu.usbmodem83301'
s = serial.Serial(port, 115200, timeout=0.1)
# DTR/RTS をパタパタして手動リセット
s.dtr = False; s.rts = True; time.sleep(0.1)
s.dtr = False; s.rts = False; time.sleep(0.1)
deadline = time.time() + 5
buf = b""
while time.time() < deadline:
chunk = s.read(4096)
if chunk:
buf += chunk
sys.stdout.buffer.write(chunk)
sys.stdout.buffer.flush()
s.close()使い方:
bash
python3 scripts/serial-snapshot.pyC. macOS 標準の screen を使う
screen も対話用だが TTY を強制割り当てするので起動は通る(ただしバックグラウンドからは結局使いにくい)。
bash
screen /dev/cu.usbmodem83301 115200
# 終了: Ctrl+A → K → yD. tio (推奨される代替)
bash
brew install tio
tio /dev/cu.usbmodem83301tio は色付き表示・ログファイル保存・自動再接続などが付いていて使い勝手が良い。
自動化したいときは
CI で「書き込んでログを取って assertion する」みたいなことをやりたい場合は ESP-IDF の idf.py monitor より、pyserial 直叩き の方が組み込みやすい。
ボードがフリーズしてないかチェックするだけなら、pyserial で Serial.println の特定文字列が一定時間内に来るか見る、という形にする。
学び
- 対話 UI 前提のツールを自動化に使おうとすると詰む — Web 開発でも
vimを CI で呼ぼうとして同じ問題に当たる - そういうときは「ターミナルが要求している基本機能(TTY、stdin など)」を提供できるかを確認する
- たいてい同じ仕事を ライブラリレイヤ(pyserial 等) で書き直せる