유닉스 쉘 "stdin / stdout API"는 얼마나 안정적입니까?


20

grepping, awking, sedding 및 pipeing은 Unix와 같은 운영 체제 사용자의 일상적인 루틴이며 명령 줄이나 셸 스크립트 ( 지금부터 필터 라고 함 )에있을 수 있습니다.

본질적으로 "표준"Unix CLI 프로그램 및 쉘 내장 ( 현재부터 명령 이라고 함)으로 작업 할 때 , 필터는 올바르게 작동하려면 각 필터 단계에서 stdin, stdout 및 stderr에 대해 정확한 예상 형식이 필요합니다. 이 명령의 정확한 형식을 다음 명령에서이 명령의 API라고합니다.

웹 개발 경험이있는 사람은 이러한 종류의 데이터 수집 및 데이터 처리를 기술적으로 웹 스크래핑 과 비교합니다. 이는 데이터 표시에 약간의 변화가있을 때마다 매우 불안정한 기술입니다.

내 질문은 이제 유닉스 명령 API의 안정성과 관련이 있습니다.

  1. 유닉스 계열 운영 체제의 명령은 입력 및 출력과 관련하여 공식적인 표준화를 준수합니까?
  2. 이전에는 일부 중요 명령을 업데이트하여 이전 버전의 해당 명령을 사용하여 작성된 일부 필터의 기능을 손상시키는 사례가 있었습니까?
  3. 시간이 지남에 따라 유닉스 명령이 성숙해지면서 일부 필터가 파손될 수있는 방식으로 변경하는 것이 절대 불가능합니까?
  4. 명령 API 변경으로 인해 필터가 수시로 중단되는 경우 개발자가이 문제로부터 필터를 보호하려면 어떻게해야합니까?

답변:


17

POSIX 2008 표준에는 "쉘 및 유틸리티"를 설명하는 섹션이 있습니다. 일반적으로 사용 중단 가능성을 제외하고는 스크립트가 미래에 대비해야하지만 밤새 거의 발생하지 않으므로 스크립트를 업데이트 할 시간이 충분해야합니다.

단일 유틸리티의 출력 형식이 플랫폼과 버전에 따라 크게 다른 경우 POSIX 표준에는 일반적으로 호출 -p되거나 -P보장되고 예측 가능한 출력 형식을 지정 하는 옵션이 포함될 수 있습니다 . 이에 대한 예는 time유틸리티 이며, 다양한 구현이 있습니다. 안정적인 API / 출력 형식이 필요한 경우을 사용 time -p합니다.

POSIX 표준에서 다루지 않는 필터 유틸리티를 사용해야하는 경우 웹 스크래핑을 수행 할 때 원격 웹 개발자가 원하는 것처럼 배포 패키저 / 업스트림 개발자의 도움을받습니다.


12

나는 나의 경험으로부터 대답하려고 노력할 것이다.

  1. 명령은 공식적인 사양을 따르지 않지만 줄 지향적 텍스트를 소비하고 생성하기위한 요구 사항을 준수합니다.

  2. 물론입니다. GNU 유틸리티가 사실상의 표준이되기 전에, 많은 벤더들은 특히 psand 와 관련하여 기발한 결과를 얻었을 것 ls입니다. 이것은 많은 고통을 초래했습니다. 오늘날 HP만이 매우 기발한 명령을 제공합니다. 역사적으로, BSD (Berkeley Software Distribution) 유틸리티는 과거에 중대한 휴식이었습니다. POSIX 사양은 과거와 단절되었지만 이제 널리 채택되었습니다.

  3. 유닉스 명령은 시간이 지남에 따라 완성되었습니다. 이전 버전 용으로 작성된 일부 스크립트를 중단하는 것은 여전히 ​​불가능하지 않습니다. 텍스트 파일 인코딩으로 UTF-8에 대한 최근 추세를 생각해보십시오. 이 변경은와 같은 기본 유틸리티를 변경해야했습니다 tr. 과거에는 간단한 텍스트가 거의 항상 ASCII (또는 비슷한 것) 였으므로 대문자와 같이 소문자와 마찬가지로 숫자 범위가 형성되었습니다. UTF-8에서는 더 이상 사실이 아니므로 tr"대문자"또는 "영숫자"와 같은 항목을 지정하기 위해 다른 명령 행 옵션을 허용합니다.

  4. 필터를 "강화"하는 가장 좋은 방법 중 하나는 특정 텍스트 레이아웃에 의존하지 않는 것입니다. 예를 들어, cut -c10-24행의 위치에 따라 하지 마십시오 . 사용 cut -f22, 탭으로 구분 필드를 잘라 것이다, 대신. awk모든 입력 라인을 $ 1, $ 2, $ 3 ...으로 나누고 기본적으로 공백으로 구분합니다. 열 위치와 같은 하위 개념보다는 "필드"와 같은 상위 개념에 의존합니다. 또한, 정규 표현식을 사용 sed하고 awk두 입력의 어떤 변화에 대한 상관 없어 정규 표현식으로 일을 할 수있다. 또 다른 요령은 필터를 까다로운 형식으로 입력을 처리하는 것입니다. tr -cs '[a-zA-z0-9]' '[\n]'문장 부호없이 한 줄에 한 단어 씩 텍스트를 나누는 데 사용 합니다. 당신은 단지


9

먼저 질문에 대한 간단한 답변입니다.

  1. 입력 / 출력 규칙의 형식 표준화 : 아니오
  2. 출력 변경으로 인한 과거 파손 :
  3. 미래 필터를 깰 절대적으로 불가능 : 없음
  4. 변화로부터 자신을 보호하는 방법 : 보수적

"API"라고 말하면 필터 입 / 출력 규칙에 대해 너무나 좋은 형식을 의미하는 용어를 사용하는 것입니다. 매우 광범위하게 (그리고 "매우"를 의미 함) 쉽게 필터링 할 수있는 데이터의 기본 규칙은 다음과 같습니다.

  • 각 입력 줄은 완전한 기록입니다
  • 각 레코드 내에서 필드는 알려진 구분 문자로 구분됩니다.

전형적인 예는 / etc / passwd 형식입니다. 그러나 이러한 기본 규칙은 서신에 따르는 것보다 어느 정도 더 자주 위반 될 수 있습니다.

  • 여러 줄 입력 형식을 구문 분석하는 많은 필터 (주로 awk 또는 perl로 작성)가 있습니다.
  • 잘 정의 된 필드 구조가없는 입력 패턴 (예 : / var / log / messages)이 많으므로보다 일반적인 정규식 기반 기술을 사용해야합니다.

네 번째 질문, 출력 구조의 변화로부터 자신을 보호하는 방법은 실제로 할 수있는 유일한 질문입니다.

  • 말했다 jw013 @ 는 POSIX 표준의 말에,보기. 물론 posix는 입력 소스로 사용하려는 모든 명령을 지정하지는 않습니다.
  • 스크립트를 이식 가능하게하려면, 어떤 명령의 어떤 버전에 대한 특유의 동기를 피하십시오. 예를 들어, 표준 GNU 명령의 많은 GNU 버전에는 비표준 확장자가 있습니다. 이것들은 유용 할 수 있지만 최대한의 이식성을 원한다면 피해야합니다.
  • 플랫폼에서 명령 인수 및 출력 형식의 하위 집합이 안정적인 경향이 있는지 알아보십시오. 불행히도, 이러한 차이는 비공식적으로도 어디에도 기록되지 않기 때문에 시간과 함께 여러 플랫폼에 액세스해야합니다.

결국, 당신은 당신이 걱정하는 문제들로부터 자신을 완전히 보호 할 수 없으며, 특정 명령이 무엇을해야하는지에 대한 "결정적인"진술을 찾아 볼 곳이 없습니다. 많은 셸 스크립트, 특히 개인 또는 소규모 사용을 위해 작성된 셸 스크립트의 경우 이는 문제가되지 않습니다.


5

귀하의 질문 중 1) 만 포함합니다.

당연히 API는 제작자의 의사에 따라 언제든지 변경 될 수 있으므로 모든 언어에서 종속 소프트웨어를 중단 할 수 있습니다. 즉, 유닉스 툴의 I / O "API"에 대한 좋은 아이디어 는 실제로는 아무것도 없다는 것 0x0a입니다. 좋은 스크립트는 데이터를 작성하는 대신 Unix 도구로 데이터를 필터링 합니다. 즉, 입력 또는 출력 사양이 변경 되었기 때문에 스크립트가 중단 될 수 있지만 스크립트에 사용 된 개별 도구의 I / O 형식 (실제로는 존재하지 않음)이 변경되지 않았기 때문에 (실제로 존재하지 않는 무언가 때문에) 실제로 변경할 수 없습니다).

기본 도구 목록을 살펴보면 필터만 이 아니라 생산자 속성을 지정하는 것이 거의 없습니다 .

  • wc- 바이트 수, 단어 수, 행 수를 인쇄합니다. 매우 간단한 형식이므로 절대로 변경 될 가능성이 없으며 스크립트에서 사용되지 않을 가능성이 높습니다.
  • diff- 다른 출력 형식이 발전했지만 문제에 대해 들어 보지 못했습니다. 또한 일반적으로 감독 없이는 사용되지 않습니다.
  • 날짜 -이제 여기서는 특히 시스템 로캘과 관련하여 우리가 생산하는 것을 관리해야합니다. 그러나 그렇지 않으면 출력 형식이 RFC로 지정되어 있으므로 직접 지정하지 마십시오.
  • cal- 그것에 대해 이야기하지 말고 출력 형식이 시스템마다 크게 다르다는 것을 알고 있습니다.
  • LS , , , 지난 - 당신이 LS를 구문 분석하려면 나는, 그냥 의미되지 않았다 없습니다 도움이 될 수가되게합니다. 또한 누가 대화 형 목록 작성자입니까? 스크립트에서 그것들을 사용한다면 당신이하는 일을주의해야합니다.
  • 다른 게시물에서 시간 이 지적되었습니다. 그러나 그렇습니다. ls와 동일합니다. 대화식 / 로컬 사용을위한 추가 정보. 그리고 bash 내장은 GNU 버전과 매우 다르며 GNU 버전은 수년간 버그가 수정되지 않았습니다. 그것에 의존하지 마십시오.

다음은 바이트 스트림보다 더 구체적인 특정 입력 형식을 예상하는 도구입니다.

  • bc , dc- 계산기. 이미 더 해킹 된 측면 (실제로는 스크립트에서 사용하지 않음)과 아마도 매우 안정적인 I / O 형식입니다.

파손 위험이 훨씬 높은 다른 영역, 즉 명령 줄 인터페이스가 있습니다. 대부분의 도구는 시스템과 타임 라인에서 서로 다른 기능을 가지고 있습니다. 예는

  • 정규식 -정규식을 사용하는 모든 도구 는 시스템 로케일 (예 : LC_COLLATE)에 따라 의미를 변경할 수 있으며 정규식 구현에는 많은 미묘함과 세밀 함이 있습니다.
  • 멋진 스위치를 사용하지 마십시오. man 1p find예를 들어 시스템 맨 페이지 대신 POSIX find 맨 페이지를 읽는 데 쉽게 사용할 수 있습니다 . 내 시스템에는 맨 페이지 -posix가 설치되어 있어야합니다.

그리고 이러한 스위치를 사용할 때에도 일반적으로 오류가 미묘하게 발생하지 않으며 데이터를 독살하지 않습니다. 대부분의 프로그램은 알 수없는 스위치로 작업하는 것을 거부합니다.

결론적으로, 쉘은 실제로 가장 이식 가능한 언어 중 하나가 될 가능성이 있다고 말할 것입니다 (휴대용 스크립트를 작성할 때 이식 가능합니다). 미묘한 오류가 발생하는 즐겨 사용하는 스크립팅 언어 또는 컴파일에 실패하는 즐겨 사용하는 컴파일 된 프로그램과 비교하십시오.

또한 비 호환성으로 인해 파손이 발생할 수있는 드문 장소에서는 아마도 시간 때문이 아니라 여러 시스템의 다양성 때문에 (20 년 전과 20 년 후) ). 그것은 도구의 단순성에 대한 결과입니다.


1

사실상 IO 표준, 공백 및 널로 구분 된 출력 만 있습니다.

호환성과 관련하여 일반적으로 개별 필터의 버전 번호 확인으로 돌아갑니다. 그것들이 많이 변하는 것은 아니지만, 새로운 기능을 사용하고 이전 버전에서 스크립트를 계속 실행하고자 할 때, 어떻게 든 "ifdef"해야합니다. 실제로는 기능보고 메커니즘이 없으므로 수동으로 테스트 사례를 작성하지 않아도됩니다.


0

스크립트는 다른 스크립트보다 더 자주 중단됩니다. 오래되고 유명한 소프트웨어는 상대적으로 동일하게 유지되는 경향이 있으며, 어쨌든 변경 될 때 종종 호환성 플래그가 있습니다.

한 시스템에서 작성된 스크립트는 작동하는 경향이 있지만 종종 다른 시스템을 손상시킵니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.