임베디드 serial console getty — 어떻게 켜나?

serial getty 임베디드 설정은 “커널이 메시지를 보낸 포트”와 “로그인 프롬프트를 띄울 포트”를 맞추는 일입니다. 한 줄로 말하면, 커널 console=에 잡은 시리얼 TTY에는 systemd-getty-generator가 serial-getty@.service를 자동으로 붙이고, 그 밖의 포트는 systemctl enable --now serial-getty@<tty>.service로 명시합니다. 이 글은 systemd-getty-generator(8), serial-getty@.service, 커널 Serial Console을 근거로 한 최소 howto입니다. 보드별 baud 일화·가격·제휴는 없습니다.

유닛/시리얼 장치는?

한 줄 답: 장치는 /dev/ttyS0, /dev/ttyAMA0, /dev/ttymxc0처럼 커널이 만든 TTY 노드이고, 유닛은 템플릿 **serial-getty@.service**의 인스턴스(serial-getty@ttyS0.service)입니다. 커널 콘솔로 지정된 시리얼이면 generator가 부팅 시 인스턴스를 끌어옵니다.

정리하면:

  • 커널 콘솔 경로: 부트로더/커널 cmdline에 console=ttyS0,115200n8처럼 넣으면, 커널 로그와 함께 generator가 serial-getty@ttyS0.service를 인스턴스화합니다(systemd-getty-generator).
  • 추가 포트 경로: 커널 콘솔이 아닌 두 번째 UART 등에 로그인이 필요하면 명시적으로 enable합니다.
systemctl enable --now serial-getty@ttyS1.service
  • 유닛은 BindsTo=dev-%i.device / After=dev-%i.device로 해당 장치 유닛에 묶입니다. 장치가 없으면 getty도 따라가지 않습니다.
  • VT(/dev/tty0 계열)는 가상 콘솔 쪽 getty@.service 영역입니다. 시리얼·하이퍼바이저 콘솔 쪽이 serial-getty@입니다.

장치 이름 확인 예:

ls -l /dev/ttyS* /dev/ttyAMA* /dev/ttymxc* 2>/dev/null
cat /proc/cmdline
systemctl status 'serial-getty@*.service'

포인트는 노드 이름(%I)과 유닛 인스턴스 이름이 같아야 한다는 점입니다. ttyS0인데 serial-getty@ttyUSB0을 켜면 다른 장치입니다.

baud·터미널 설정은?

한 줄 답: 시리얼 속도·패리티·비트는 우선 **커널 console=device,options**에서 잡고, getty 쪽은 기본이 **--keep-baud**라서 커널이 연 속도를 유지합니다. $TERM은 유닛의 agetty 인자에 넘깁니다.

커널 문서의 options 형식은 BBBBPNF(예: 115200n8)입니다. 기본은 9600n8이고, 시리얼 최대는 문서상 115200입니다(Serial Console).

기본 serial-getty@.service의 ExecStart 요지(배포본에 따라 경로·옵션 소폭 차이 가능):

agetty --keep-baud 115200,57600,38400,9600 - $TERM

의미:

  • --keep-baud: 이미 설정된(대개 커널 cmdline) baud를 유지합니다. 목록은 BREAK로 순환할 수 있는 후보입니다.
  • 고정 속도가 필요하면 드롭인/오버라이드로 ExecStart를 바꿉니다. 예: agetty 115200 %I $TERM 형태(배포 man·유닛 주석을 확인).
  • $TERM: 호스트 터미널 에뮬레이터와 맞춥니다. 흔한 값은 vt100, linux, xterm입니다. 잘못된 TERM은 제어 문자·화면만 깨지고, “완전 무응답”과는 다른 증상입니다.

호스트 측(PC) 시리얼 클라이언트도 같은 baud·8N1이어야 합니다. 커널/stty/클라이언트가 어긋나면 깨진 문자 또는 빈 화면처럼 보입니다.

# 타깃에서 (로그인 가능한 다른 경로가 있을 때)
stty -F /dev/ttyS0 -a
# 호스트 예 (도구마다 옵션명 상이)
# picocom -b 115200 /dev/ttyUSB0

보드마다 “반드시 이 baud”라는 창작 규칙은 두지 않습니다. cmdline·유닛·클라이언트 세 곳이 같은 값인지만 확인합니다.

안 뜨면 어디를 보나?

한 줄 답: 빈 화면(프롬프트 없음)이면 (1) 장치가 있는가 (2) console=/serial-getty@가 그 장치인가 (3) baud·배선 (4) 유닛 Active/Logs 순으로 자릅니다. “getty만 켜면 된다”보다 커널 콘솔과 로그인 경로가 같은 TTY인지가 먼저입니다.

점검 체크리스트:

  1. 물리·케이블·TX/RX 교차 — 전원·GND·교차 연결. 소프트웨어 전에 하드웨어.
  2. /proc/cmdline의 console= — 마지막 console=이 로그인/콘솔 정책에 영향을 줍니다. 커널 문서·systemd 쪽 모두 cmdline을 읽습니다.
  3. 장치 노드 존재 — ls /dev/ttyS0 등. SoC마다 ttyAMA0/ttymxc0 이름이 다릅니다.
  4. 유닛 상태
systemctl status serial-getty@ttyS0.service
journalctl -u serial-getty@ttyS0.service -b --no-pager
systemctl list-units 'serial-getty@*' --all
  1. generator가 만든 유닛인지 — cmdline에 시리얼 console=이 있으면 보통 자동입니다. 없는데 수동 enable만 했다면 baud·장치만 맞으면 됩니다.
  2. 커널 메시지는 보이는데 login만 없음 — getty/유닛/BindsTo 장치 실패를 의심. login도 커널도 없음 — baud·포트·배선·잘못된 TTY 이름을 의심.
  3. BusyBox/agetty 부재 — 이미지가 agetty/getty를 안 넣으면 유닛이 바로 실패합니다. 이미지 패키지 목록을 확인합니다.
증상먼저 볼 곳
완전 무응답배선·포트 번호·호스트 장치 노드
깨진 문자baud/parity 불일치
커널 로그만, login 없음serial-getty@ status·journal·agetty 존재
유닛 faileddev-%i.device, ExecStart 경로
# 한 번에 훑기 예
echo "cmdline: $(cat /proc/cmdline)"
systemctl is-active serial-getty@ttyS0.service || true
journalctl -u serial-getty@ttyS0.service -b -n 30 --no-pager

자주 묻는 질문

커널 console=만 넣으면 getty도 자동인가? 시리얼이 커널 콘솔이고 VT가 아니면 systemd-getty-generator가 serial-getty@.service를 붙이는 것이 설계입니다. 컨테이너/가상화 환경은 별도 규칙이 있습니다.

getty@ttyS0와 serial-getty@ttyS0 중 무엇을 쓰나? 시리얼·비-VT는 **serial-getty@**가 맞습니다. VT용 getty@와 템플릿·옵션이 다릅니다.

baud를 유닛에서만 바꿔도 되나? 가능하지만, 커널 early console과 로그인 속도가 갈라질 수 있습니다. 가능하면 cmdline과 getty를 같이 맞춥니다.

정리

임베디드에서 serial getty는 **장치 노드 + serial-getty@ 인스턴스 + (대개) console=**의 삼각형입니다. baud는 커널 options와 --keep-baud를 먼저 보고, 빈 화면이면 장치·유닛 journal·클라이언트 속도를 같은 순서로 확인합니다.

공식 문서는 어디인가?