안전한 고양이는 있나요?

안전한 고양이는 있나요?

때때로 컬이나 로컬 파일 시스템에서 바이너리를 캐팅하는 경우가 있습니다. 대부분의 경우 깨진 터미널은 다음과 같은 방법으로 고칠 수 있습니다.초기화. 다른 경우, 특히 바이너리가 큰 경우 터미널은 다음과 같이 출력을 인쇄하는 데 몇 분 동안 멈춥니다.

2c1

일명

c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;
2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;2c1;

이 시나리오와 관련하여 세 가지 질문이 있습니다.

  1. 2c1은 무엇을 의미하며 터미널이 이것을 인쇄하는 이유는 무엇입니까?
  2. cat대화형 세션에서 이러한 바람직하지 않은 동작을 방지하는 것을 실제로 본 적이 있습니까 ?
  3. 그러한 고양이(cee 또는 golang)를 프로그래밍하는 방법에 대한 제안 사항이 있습니까?

나의 초기 본능은 이것을 감지하기 위해 cat을 함수로 감싸는 것이었지만, 이것이 꽤 어렵고 여러 가지 예외적인 경우가 있다는 것을 곧 깨달았습니다.

function cat() {
    # warn user if
    #   - argument 1 is a large  executable 
    #   - argument 1 to the previous command in the a pipe-chain looks like a large binary
    # abort if
    #   - session is interactive and we are able to detect 2c1 garbage
}

실용적인 해결책은 "안전하지 않은" 입력을 볼 때 항상 LESSPIPE를 사용하여 더 적게 사용하는 것일 수 있지만 이 질문은 호출기에 관한 것이 아닙니다. 나는 less와 lesspipe에 대해 알고 있습니다. 나는 매일 적극적으로 사용합니다. 아마도 덜+파이프가 없을 수도 있습니다이 문제에 대한 해결책은 약 20~30년 전에 덜 구현된 작성자가 동일한 문제에 직면했다는 것입니다..

그러나 고양이는 여러 면에서 "호출기"와 다릅니다. 주로 고양이는 비대화형입니다. 이것은 나에게 중요합니다.

less+lesspipe에 대한 제안은 실용적인 측면에서 정말 훌륭하지만(imho) 제어 문자의 핵심, 특수 이스케이프 시퀀스 및 다양한 터미널이 이러한 입력을 처리하는 방법에 더 관심이 있습니다.

나는 제어 문자의 기술적인 세부 사항과 터미널이나 쉘이 "쓰레기"와 제어 문자를 해석하는 방법에 더 관심이 있습니다. 나는 "이 문제를 어떻게 해결하시겠습니까?"라고 묻는 것이 아닙니다. 나는 "터미널이 왜 이런 바이너리 파일을 처리하는가"라고 묻고 있습니다.

답변1

less대신에 바이너리 파일에 대해 경고하고 일부 시스템에서는 다양한 종류를 처리할 수 있는 기능을 사용하겠습니다 (예를 들어CentOS 7에서는 less file.rpmRPM의 파일을 볼 수 있습니다. 나는 그것이 "레스파이프(lesspipe)"라고 불린다고 믿습니다.

또한 다음에 그런 일이 발생하면 정상으로 돌아가려고 reset노력할 수 있습니다. 이는 기본 정상적인 상태로 재설정 하고 tty 장치 파일의 설정을 정상적인 기본값으로 변경하는 것과 tput reset동일한 작업을 수행하도록 터미널에 이스케이프 시퀀스를 보냅니다 (바이너리 파일을 덤프해도 영향을 미치지 않아야 함). 또한 쿼리를 지원하는 터미널을 사용하여 터미널 또는 터미널 에뮬레이터(에서 보고한 대로)의 창 크기에 대한 tty 장치 파일의 개념을 수정할 수도 있습니다 .stty saneresettty size

답변2

아무도 '문자열'을 언급하지 않았습니다. 문자열은 정확히 cat과 같지는 않지만 터미널에서 더 안전하게 볼 수 있도록 연속 텍스트 데이터에서 텍스트 문자열만 인쇄합니다. 일반적으로 binutils 패키지와 함께 제공됩니다. 이는 인쇄된 데이터에서 바이너리 출력을 얻지 못하도록 신속하게 확인하는 편리한 프로그램이며 연속적인 비바이너리를 보고 싶은 경우에도 유용합니다. 기본적으로 4개 이상의 ASCII 문자가 포함된 연속 텍스트 섹션만 ​​인쇄합니다. 이는 -n 옵션으로 조정할 수 있습니다.

답변3

직렬 회선 또는 의사 tty 장치(직렬 회선을 에뮬레이트하는)를 통해 터미널 또는 터미널 에뮬레이터와 상호 작용합니다.

커널에는 일종의 적응 계층으로 중간에 위치하여 일부 변환(나중에 간략하게 설명)을 수행하는 소프트웨어 모듈이 있지만 일반적으로 다음을 수행합니다.

  • 터미널이 화면에 렌더링할 문자 또는 동작을 변경하기 위한 특수 명령으로 해석하는 직렬 회선을 통해 바이트 스트림을 터미널에 보냅니다.
  • 그 대가로 터미널은 해당 직렬 회선의 다른 와이어를 통해 컴퓨터에 바이트 스트림을 보내 사용자가 입력한 내용을 컴퓨터에 알리거나 컴퓨터가 받은 제어 쿼리 중 일부에 응답합니다.

예를 들어, 터미널은 ISO8859-1(latin1 터미널이라고도 함)로 구성될 수 있습니다. 즉, 0x53 0x74 0xe9 0x70 0x68 0x61 0x6e 0x65를 수신하면 터미널에서 S, t, é, p, h, a, n, e글리프를 렌더링하는 것으로 해석합니다. 화면의 현재 커서 위치. 반대로 사용자가 를 입력하면 S터미널은 0x53 바이트를 보냅니다.

0에서 0x1f 범위의 바이트 값은 다음과 같이 해석됩니다.제어문자. 즉, 글리프로 표현되지는 않지만 특별한 의미를 갖습니다.

예를 들어:

  • 0x7(BEL)은 오디오 또는 비디오 경고를 생성합니다.
  • 0x8(BS)은 커서를 왼쪽으로 이동합니다.
  • 0xa(LF)는 커서를 아래로 이동합니다.
  • 0xd(CR)는 커서를 화면의 첫 번째 열로 이동합니다.
  • 0x9(TAB)는 커서를 다음 표로 이동합니다.

해당 범위에는 32개의 제어 문자만 있으며 대부분의 터미널에는 더 많은 기능이나 제어 방법이 있습니다. 따라서 그 외에도 다음 이상의 시퀀스를 보낼 수 있습니다.하나터미널을 제어하기 위한 바이트입니다. 대부분의 터미널과 대부분의 시퀀스에서 첫 번째 바이트는 0x1b(ESC)이고 그 뒤에는 하나 이상의 바이트가 있습니다.

예를 들어, 위에서 본 것처럼 커서를 왼쪽이나 아래로 이동하는 제어 문자는 있지만 오른쪽이나 위로 이동하는 제어 문자는 없습니다(원래 텔레 타자기에서 오른쪽은 "스페이스"로 수행되지만 커서 아래에 있는 내용을 지우는 CRT 터미널과 텔레타자기를 사용하면 종이 걸림이 발생할 수 있으므로 이스케이프 시퀀스를 도입해야 했습니다. 대부분의 터미널에서는 각각 0x1b 0x5b 0x43 및 0x1b 0x5b 0x41이었습니다. (덧붙여서, 이는 많은 터미널이 해당 키를 가진 터미널에 대해 Right및 키를 누를 때 전송하는 바이트 시퀀스이기도 합니다 Up.)

이제 터미널이 지원하는 이스케이프 시퀀스 중에는 다음이 포함됩니다.

  • 텍스트나 배경색 및 기타 그래픽 렌더링 속성을 변경합니다.
  • 문자셋을 변경하세요. 예를 들어 latin1에는 그리스어 문자가 없으며 터미널(유니코드 이전 시대부터 현재까지)은 다른 언어 문자 또는 상자 그림 문자를 표시하기 위해 다른 문자 세트로 전환하는 것을 지원합니다.
  • 탭 정지 위치 설정
  • 커서 위치, 색상, 창 제목, 크기 등의 정보를 터미널에서 쿼리할 수 있습니다.
  • 입력이 처리되는 방식에 영향을 줄 수 있습니다. 예를 들어, 일부 터미널은 Shift+를 누르면 A0x41(ASCII A) 문자가 아니라 수정자(shift, alt, ctrl...) 및 키코드에 대한 정보를 인코딩하는 바이트 시퀀스를 보내는 모드로 들어가는 것을 지원합니다.
  • 일부 X11 터미널 에뮬레이터는 글꼴, 창 크기를 변경하고 JPEG 이미지를 표시하고 화면 내용을 프린터로 보내기 위해 이스케이프 시퀀스를 인식합니다.

텍스트 파일에는 일반적으로 그래픽 문자를 나타내는 바이트(또는 UTF-8 또는 기타 멀티바이트 문자 집합의 경우 바이트 시퀀스)만 있습니다. 유일한제어텍스트 파일에서 찾을 수 있는 문자는 NL(0xa, 일명 LF) 및 TAB(0x9)입니다.

그렇게 하면 cat file.txtcat내용을 읽고 file.txt표준 출력에 씁니다. stdout 이 터미널 에뮬레이터의 대화형 쉘에서 해당 명령을 실행하는 경우처럼 터미널 라인 규칙이 푸시된 직렬 또는 의사 tty 장치 파일(예: )인 경우 /dev/ttyS0라인 규칙은 해당 NL을 변환합니다. /dev/pts/0CR+NL로(NLNL은 단지 CRNLNL로 변환될 수 있음) CRNL을 수신하면 터미널은 커서를 시작 부분으로 이동한 다음 아래로 이동합니다.

따라서 파일 내용의 텍스트가 터미널의 문자 집합으로 인코딩된 경우 파일 내용의 텍스트가 터미널 화면에 표시됩니다.

이제 실행 파일이나 기타 임의의 이진 파일의 바이트는 문자를 나타내기 위한 것이 아니며 0에서 31 범위의 값을 포함하여 모든 값을 가질 수 있으므로 터미널로 전송되면 터미널은 지시된 대로 수행하고 이를 다음과 같이 해석합니다. 제어 문자로 인해 위에 나열된 작업과 그 이상을 수행할 수 있으며 완전히 사용할 수 없게 될 수 있습니다.

이를 방지하기 위해 먼저 해당 파일을 터미널에 보내지 마십시오. 이는 말이 되지 않거나 파일이 텍스트 파일(또는 사용자가 문자 그대로 볼 수 있도록 의도된 파일)일 수 있는지 여부를 알 수 없는 경우입니다. 이스케이프 시퀀스가 ​​있는 터미널예정된터미널에서 해석되도록) 제어 문자(적어도 TAB 및 NL을 제외한 모든 문자)를 제거하거나 시각적 그래픽 표현을 제공하는 도구를 사용할 수 있습니다.

이것이 바로 많은 구현 에서 지원되는 -v및 옵션이 수행하는 작업입니다. 를 사용하면 NL 및 TAB를 제외한 모든 문자는 비ASCII 문자의 일반적인 시각적 표현인 바이트 0~31 및 0x7f, 바이트 0x80~0x9f 및 0xff, 바이트 0xa0~0xfe 에 대한 일부 표기법으로 변환됩니다 . 그리고 TAB에 대해서만 수행합니다( 로 변경됨 ).-tcat-v^XM-^XM-X-t^I

또는 기본적으로 (적어도 / raw 옵션 을 사용하지 않는 한 ) less또는 와 vim같은 호출기를 사용할 수 있으며 비ASCII 문자를 변환하지 않는다는 점에서 조금 더 똑똑합니다. 해당 로케일에 그래픽 표현이 있고 색상 지정 또는 눈에 띄는 모드를 사용하여 어떤 바이트가 변환되었는지 더 명확하게 만들기 위한 것입니다.view-r-R

hexdump -C또는 또는 와 같은 텍스트가 아닌 파일을 미리 보는 전용 도구를 사용할 수 있습니다 xxd.

덜 모호한 방식으로 와 유사한 작업을 수행하고 표준인( 와 반대되는 ) l명령 도 참조하세요 .sedcat -vtecat -vte

sed -n l < a-file

답변4

  • 응, 젊은 파다완.
$ cargo search bat 
bat = "0.23.0"            # A cat(1) clone with wings.
  • 그런데 선생님, 화물이 뭔가요?
$ cargo --help |any install rust 
Rust's package manager
      --list                List installed commands
      --explain <CODE>      Run `rustc --explain CODE`
    install     Install a Rust binary. Default location is $HOME/.cargo/bin
    uninstall   Uninstall a Rust binary
$ cargo install bat
(...)

주인:bat바이너리를 시도하면 이런 일이 발생합니다 .

$ bat `which bat`
[bat warning]: Binary content from file '/home/jaroslav/.cargo/bin/bat'
will not be printed to the terminal (but will be present if the output
of 'bat' is piped). You can use 'bat -A' to show the binary file contents.
  • 파다완:배트에도 단점이 있나요, 마스터?
  • 주인:예, 대용량 파일에서는 속도가 느려질 수 있지만 이는 부분적으로 구조화된 구문을 강조하기 때문입니다. 해당 항목은 비활성화할 수 있습니다. 예: --style=plain --color=never
  • 파다완:그러면 cat이 터미널에 출력하는 이상한 문자는 어떻습니까, 마스터?
  • 주인:이는 터미널이 ANSI 이스케이프 코드(내부 터미널 명령)처럼 보이는 모든 것을 기꺼이 받아들이고 해석하고 해당 명령이 구현된 경우 명령이 말하는 대로 수행하려고 시도하기 때문에 발생합니다. 간략한 소개는 다음을 확인하세요.ANSI 색상 이스케이프 시퀀스 목록

이 동작을 재현하는 방법은 다음과 같습니다.

$ echo -ne "\u1B\u5B\u63" | xxd
00000000: 1b5b 63                                  .[c

$ echo -ne "\u1B\u5B\u63" 
^[[?1;2c

$ 1;2c

관련 정보