쉘 스크립트의 출력(사용자가 입력한 텍스트 포함)을 터미널과 로그 파일로 보내고 싶습니다.
tee
나는 와 의 어떤 조합이 트릭을 수행할 수 있다고 생각 exec
하지만 지금까지는 운이 없었습니다. tee
사용자가 터미널에 입력하는 내용을 자체적으로 에코하고 캡처할 수 있다는 것을 알고 있습니다 .
$ tee logfile
Hello (I entered this at runtime)
Hello (I entered this at runtime)
^C
$ cat logfile
Hello (I entered this at runtime)
하지만 쉘 스크립트에서 호출된 명령에 대한 응답으로 사용자가 입력하는 내용을 터미널과 로그 파일 모두에서 확인해야 합니다.
tee
지속적으로 할 수는 없을 것 같습니다.
예를 들어:
$ read message 2>&1 | tee logfile
Hello (I entered this at runtime)
$ cat logfile
거기에는 아무것도 포착되지 않았습니다. Hello (I entered this at runtime)
예전처럼 파일로 볼 수 있었으면 좋겠습니다 .
또한 다음과 같은 쉘 스크립트로 결합해 보았습니다 tee
.exec
$ cat test.bash
#!bin/bash
# Note: in this simplified version of this file, I’m not looking at $1, $2, or anything else passed in, but will need to eventually
rm -f logfile
exec &> >(tee -a logfile)
echo “Say \”Hello\”” 2>&1
read -p “> “ 2>&1
불행히도 추가 exec
:
$ ./test.bash
Say “Hello”
> Hello (I entered this at runtime)
$ cat logfile
Say “Hello”
>
echo
보시다시피, 명령과 명령의 출력은 캡처 read
하지만 명령에 대한 응답으로 터미널에 입력한 내용은 캡처하지 않습니다 read
.
그것을 할 수 있는 방법이 있나요?
나는 script
명령("make typescript of Terminal session")이 화면의 모든 것을 캡처하여 로그 파일에 저장한다는 것을 알고 있습니다. 그러나 script
명령은 쉘 스크립트에서 유용한 방식으로 호출될 수 없습니다. (그럴 수 있나요?)
script
먼저 호출해야 하며, 그런 다음 사용자는 필요한 쉘 스크립트를 호출해야 합니다. 하지만 나는 사용자가 명령과 해당 인수를 호출하고 해당 명령이 다른 모든 것을 실행하고 모든 것을 기록하도록 하길 원합니다.
그러면 스크립트에서 캡처한 모든 "추가" 정보(예: 색상 코드, 백스페이스 키)로 인해 텍스트 편집기에서 결과 로그 파일을 읽기가 어렵습니다.
로그 파일에서 "사람이 읽을 수 있는" 문자를 보고 싶습니다. 사용자가 철자 오류를 수정했는지 확인하고 싶지 않습니다. 편집을 마치고 Enter 키를 눌렀을 때 "Hello"가 화면에 나타나는 것을 보고 싶습니다. 캡처 후 추가 정보가 제거될 수 있다고 생각합니다.
답변1
script
최소한 구현은 util-linux
스크립트 가능합니다.
예를 들어 다음과 같이 할 수 있습니다.
SHELL=/bin/sh script -qec '
# any sh code here
echo Whatever
cat # user input' file.log
file.log
다음을 포함하여 터미널에 기록된 모든 내용을 캡처 합니다 .에코당신이 입력한 것. 여기에는 LF에서 CRLF로의 변환과 같은 tty 라인 규칙에 의해 수행되는 변환도 포함됩니다.
script
또한 일부 추가됨
Script started on 2021-09-29 14:58:59+01:00 [TERM="screen.xterm-256color" TTY="/dev/pts/8" COLUMNS="191" LINES="54"]
헤더 및:
Script done on 2021-09-29 14:58:59+01:00 [COMMAND_EXIT_CODE="0"]
바닥글은 ksh 스타일 프로세스 교체 지원을 통해 셸에서 제거됩니다. 다음을 사용하여 제거할 수 있습니다.
SHELL=/bin/sh script -qec '...' >(sed '1d;$d' > file.log)
또는 @zevzek이 제안한 대로 script
헤더/바닥글을 포함하여 로그에 기록하도록 지시 /dev/null
하고 script
출력( -q
머리글이나 바닥글 없이)을 tee
로깅으로 리디렉션합니다.
(set -o pipefail; SHELL=/bin/sh script -qec '...' /dev/null | tee file.log)
zsh
또는 on을 사용하여 multi_ios
(기본적으로):
SHELL=/bin/sh script -qec '...' /dev/null >&1 > file.log
의사 tty 시작에 대한 tty 행 규칙에 의한 출력 사후 처리를 비활성화하려면 script
다음과 같이 최소한 호스트 tty에서 이를 비활성화하고 NL -> CRNL 변환을 다시 활성화할 수 있습니다.
SHELL=/bin/sh HOST_TTY="$(tty)" script -qec '
stty -opost && stty < "$HOST_TTY" opost onlcr || exit
...' file.log
( 의 명령이 ...
이 출력 처리를 복원하지 않는다고 가정합니다.)
답변2
애플리케이션이 tty 장치에 읽고 쓰는 내용을 기록하는 또 다른 방법은 strace -P "$(tty)"
tty에 대한 모든 시스템 호출을 기록하고 읽기 및 쓰기에 대한 16진수 덤프를 포함하는 것입니다. 그런 다음 xxd를 사용하여 디코딩할 수 있습니다.
strace -f -e read=all -e write=all \
-e trace='read,write' \
-P "$(tty)" \
-e status=successful -o '|
grep "^ "|cut -b11-60 | xxd -p -r > file.log
' -qqs0 -a0 cat
답변3
사용tee
이 구문을 사용하십시오.
read message
echo "${message}" | tee file
file
귀하의 의견이 완료될 때까지 귀하의 의견이 거기에 있을 것이라고 보장할 수 있습니다.