
임베디드 Linux를 실행 중이고 명령줄에 console=/dev/ttyO0,...
. 이 UART에 터미널 프로그램이 연결되어 있으며 볼 수 있습니다모든 것시스템에 의해 생산됩니다.
이제 현장에서 실행할 때 이 모든 출력을 파일에 저장하고 싶습니다(미디어가 연결되어 있습니다). 그러나 syslogd
, klogd
및 Co.를 사용한 모든 노력은 logger
원하는 결과를 제공하지 못했습니다. 일부 메시지는 저장되지만 일부는 저장되지 않습니다. 일반적으로 가장 중요합니다.
예를 들어, 다음을 실행하면:
myapplication.sh | logger
echo
에서 볼 수 있는 명령 syslog
, print
응용 프로그램의 s, 일부 드라이버 메시지도 있습니다. 그러나 분할 오류로 인해 애플리케이션이 충돌하는 경우 이 정보는 기록되지 않습니다. 그러나 이것은 가장 귀중한 것입니다!
그렇다면 가장 좋고 가장 바람직한 방법은 ttyO0
파일로 리디렉션하는 것입니다. 그런데 어떻게 해야 할까요?
나는 다음과 같은 권장 사항을 찾았습니다.
(stty raw; cat > received.txt) < /dev/ttyO0
그러나 이것은 작동하지 않습니다. 예를 들어 명령을 입력할 수 있지만 ifconfig
응답은 파일이나 콘솔에 나타나지 않습니다. 심지어 파일이 생성되지도 않습니다...:-(
파일과 직렬 콘솔을 모두 가질 수 있다면 정말 좋을 것입니다. 그러나 파일의 우선순위가 더 높습니다.
도움을 주셔서 감사합니다!
업데이트해결책을 찾아서 답변 섹션에 추가했습니다.
답변1
당신은 매우 기본적인 사실 하나를 놓친 것 같습니다. 모든 파이프 가능한 프로그램은 다음과 같은 사실에 의존합니다.삼어떤 프로그램이 호출하더라도 미리 열린 상태의 표준 파일 설명자입니다. 파이프와 관련된 대부분의 경우 호출 프로그램은 명령 셸입니다.
이 세 가지 파일 설명자는 다음과 같습니다.
- 파일 설명자 #0: 표준 입력 스트림,
stdin
줄여서 표현합니다. - 파일 설명자 #1: 표준 출력 스트림, 또는
stdout
줄여서 나타냅니다. - 파일 설명자 #2: 표준오류 출력스트림 또는
stderr
줄여서.
프로그램이 파일 읽기/쓰기를 위해 파이프되거나 리디렉션되지 않는 경우 일반적으로 이 세 가지 파일 설명자는 현재 로그인 세션이 실행 중인 TTY 장치를 가리킵니다. 프로그램이 의도적으로 데몬이나 백그라운드/비대화형 프로세스로 시작된 경우 이들 모두는 파일이나 로 전달되거나 /dev/null
일종의 로깅 기능으로 전달될 수 있습니다.
오류 메시지는 일반적으로 stderr
파이프로 연결된 데이터 출력과 혼합되지 않도록 정확하게 스트림으로 출력됩니다. 하지만 당신과 같은 경우에는 캡처하고 싶을 때모두출력을 위해서는 두 스트림을 모두 가져오도록 시스템에 명시적으로 지시해야 합니다.
모든 출력을 파이프로 전달하려면 myapplication.sh
다음과 같이 해야 할 수도 있습니다.
myapplication.sh 2>&1 | logger
"파일 설명자 #2를 #1이 가는 동일한 장소로 리디렉션"이라는 메시지 2>&1
가 나타나면 두 파일을 동시에 파이프할 수 있습니다.
다음과 같은 간단한 스크립트를 사용하여 직접 테스트할 수 있습니다.
#!/bin/sh
echo "this is stdout"
echo "this is stderr" >&2
이는 >&2
"이 명령의 표준 출력을 가져와 대신 표준 오류 스트림으로 보내는 것"을 의미합니다. 이는 아마도 stderr
스크립트에서 출력을 생성하는 가장 쉬운 방법일 것입니다 .
이제 이 스크립트를 실행하여 ./test.sh | od -t x1z
16진 덤프 형식으로 출력을 얻으면 다음과 같은 결과를 얻게 됩니다.
$ ./test.sh | od -t x1z
this is stderr
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a >this is stdout.<
0000017
따라서 명령 stdout
에 의해 출력만 처리되었습니다 od
.
두 스트림을 병합하기 위해 추가하면 2>&1
대신 다음을 얻게 됩니다.
$ ./test.sh 2>&1 | od -t x1z
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a 74 >this is stdout.t<
0000020 68 69 73 20 69 73 20 73 74 64 65 72 72 0a >his is stderr.<
0000036
이제 두 출력이 모두 파이프라인으로 전송되었습니다. 이는 | logger
.
두 번째 명령줄은 내장 장치가 터미널로 보내는 것이 아니라 내장 장치가 터미널 프로그램에서 수신하는 모든 것을 캡처합니다.
(stty raw; cat > received.txt) < /dev/ttyO0
커널 매개변수를 사용하는 임베디드 시스템에서 작업 중이므로 console=/dev/ttyO0
기본적으로 /dev/console
그래픽 디스플레이(임베디드 장치에는 존재하지 않을 수도 있음)가 아닌 직렬 포트가 될 것이라고 말씀하셨습니다.
내장 장치에서 해당 명령을 실행하는 경우 괄호 안의 명령은 해당 명령과 함께 실행됩니다.표준 입력 스트림(파일 설명자 #0 또는 stdin
줄여서) 에 할당되었습니다 /dev/ttyO0
. 그러나 에 연결된 직렬 회선을 통해 해당 명령을 입력하는 경우 ttyO0
기본적으로 그렇게 될 것이므로 이 입력 리디렉션은 상황을 그대로 다시 적용할 수 있습니다.
그만큼/dev/ttyO0
는 다른 컴퓨터의 터미널 프로그램에 연결된 UART를 직접 표현한 것입니다. 당신이 그것을 읽을 때, 당신은 얻습니다.터미널 프로그램에 입력하는 내용만: 이전에 전송된 출력을 다시 읽을 수 있는 방법이 없습니다. 그리고 거기에 쓰여진 모든 내용은 직렬 케이블 끝에 있는 터미널 프로그램으로 직접 전달됩니다.
직렬 포트의 Unix 명령줄은 일반적으로 다음과 같은 장치에서 작동합니다.원격 에코원칙: 터미널 프로그램에 작성 중인 내용을 보려면 임베디드 시스템의 TTY 드라이버는 사용자가 입력하는 모든 문자의 복사본을 터미널 프로그램으로 바로 보내야 합니다. 이 동작은 대칭적이지 않습니다. 터미널 프로그램은 직렬 포트 연결을 통해 수신한 내용의 복사본도 다시 보내지 않습니다.
TTY 드라이버는 복잡한 것입니다. 왜냐하면 Unix 전통에 따라 많은 일을 할 수 있어야 하기 때문입니다. 원격 에코 기능은 그 중 하나일 뿐입니다.
을 사용하면 stty raw
효과적으로TTY 드라이버의 일반적으로 유용한 기능을 모두 끄십시오., 원격 에코 기능을 포함합니다. 따라서 그 시점부터 명시적으로 읽고 /dev/ttyS0
즉시 다시 쓰지 않는 한 터미널 프로그램에서 작성 중인 내용을 볼 수 없습니다.
명령 이 stty raw
종료되면 터미널 프로그램의 모든 입력은 명령으로 들어가며 cat
, 매개 변수 없이 호출하면 그대로 표준 출력으로 전달됩니다. 그러나 표준 출력은 이제 파일로 리디렉션되었습니다 received.txt
. 그래서 무슨 일이 일어나는가?터미널 프로그램에 입력하는 내용만 파일에 기록됩니다.명령이 끝날 때까지 cat
- 파일 끝 문자(일반적으로 Control+D)를 얻을 때만 종료됩니다.
received.txt
(재지정을 수행하는 셸에서 버퍼링을 수행할 수 있기 때문에 파일 끝 문자로 입력을 끝내거나 두 줄 이상의 텍스트를 입력하지 않으면 파일 에 출력이 없을 수 있습니다 .)
따라서 TTY 드라이버 기능을 끄는 것 외에 (stty raw; cat > received.txt) < /dev/ttyO0
내장형 시스템에서는 아무 것도 캡처하지 않습니다.산출에 기록되고 있습니다 /dev/ttyO0
. 이 명령의 유일한 용도는 문제를 해결할 때입니다.직렬 포트 연결: 터미널 프로그램이 보내는 문자를 어떻게든 조작하고 있다는 의심이 드는 경우, 이 방법을 사용하면 터미널 프로그램이 임베디드 장치에 보내는 모든 내용을 가장 원시적인 형태로 캡처할 수 있습니다.
녹음하고 싶다면절대적으로 모든 것예를 들어 커널 패닉 메시지를 포함하여 UART 연결을 통해 발생하는 경우 가장 좋은 방법은 다른 컴퓨터의 터미널 프로그램에 모든 트래픽을 기록하도록 지시하는 것입니다. 많은 터미널 프로그램에는 이 기능이 내장되어 있습니다.
이는 커널에 문제가 발생하면 더 이상 디스크 파일에 아무것도 쓰는 것이 실제로 불가능할 수 있기 때문입니다. UART에서 오류 메시지 텍스트를 보내고 이를 수신하는 사람이 이를 발견할 것이라고 신뢰하는 것이 훨씬 간단합니다.
답변2
좋아, 답을 찾은 것 같아. 이렇게 간단하고 필요한 IMHO 문제가 이렇게 "불규칙한" 방식으로 해결된다는 사실에 매우 놀랐습니다. 하지만 이것이 인생입니다...:-)
어쨌든, telcoM
참고 자료와 더 많은 참고 자료로 이어지는 참고 자료를 주신 분께 감사드립니다. 마침내 ttyrpl
내가 원하는 것을 정확히 수행하는 패키지를 찾을 수 있었습니다 .
패키지 유지 관리는 약 7~10년 전에 중단되었으며 이를 내 Linux 버전과 필수 라이브러리에 적용하는 데 시간이 좀 걸렸지만 작동합니다!
내가 원했던 일을 정확히 수행합니다. ttyS0/ttyO0의 출력을 수집하여 파일에 저장합니다. 그리고 필요하지는 않지만 멋진 옵션이 많이 있습니다...:-)
답변3
console=/dev/ttyS0 대신 picocom을 사용해 보십시오. 다른 도구도 있지만 picocom이 가장 쉬운 것 같습니다.
이러한 도구 중 하나를 사용하면 출력에 파이프와 티를 사용할 수 있습니다.
picocom /dev/ttyS0 -b 115200 -l | tee my.log
답변4
노력하다https://tio.github.io- 파일에 대한 로깅을 지원합니다. 예를 들어:
tio /dev/ttyS0 --log --log-file my-log.txt
또는
tio /dev/ttyS0 --log
다음과 같은 자동 생성된 파일 이름을 사용하여 파일에 직렬 출력을 기록합니다.tio_ttyS0_2022-09-14T08:56:09.log