programing tip

고양이의 쓸데없는 사용?

itbloger 2020. 9. 11. 07:47
반응형

고양이의 쓸데없는 사용?


이것은 아마도 다음을 사용하는 대신 많은 FAQ에 있습니다.

cat file | command

(이것은 고양이의 쓸모없는 사용이라고 함) 올바른 방법은 다음과 같습니다.

command < file

둘째, "올바른"방법-OS는 추가 프로세스를 생성 할 필요가 없습니다.
그 사실을 알면서도 쓸모없는 고양이를 두 가지 이유로 계속 사용했습니다.

  1. 더 심미적-데이터가 왼쪽에서 오른쪽으로 만 균일하게 이동하는 것이 좋습니다. 그리고 쉽게 대체 할 cat다른 뭔가 ( gzcat, echo, ...), 제 2의 파일을 추가하거나 새 필터를 삽입 ( pv, mbuffer, grep...).

  2. 어떤 경우에는 더 빠를 수 있다고 "느낀다". 두 개의 프로세스가 있기 때문에 더 빠릅니다. 첫 번째 ( cat)는 읽기를 수행하고 두 번째는 무엇이든 수행합니다. 그리고 그들은 병렬로 실행될 수 있으며, 이는 때때로 더 빠른 실행을 의미합니다.

내 논리가 맞습니까 (두 번째 이유)?


나는 오늘까지 어떤 신인 이 내 답변 중 하나에 UUOC 를 고정하려고 시도했을 때까지 상을 알지 못했습니다 . 그것은 cat file.txt | grep foo | cut ... | cut .... 나는 그에게 내 마음의 한 조각을줬고 그렇게 한 후에야 그가 수상의 기원과 그렇게하는 관행을 언급 한 링크를 방문했다. 추가 검색을 통해이 질문을 받았습니다. 다소 안타깝게도 의식적인 고려에도 불구하고 내 근거를 포함하는 답변은 없었습니다.

나는 그에게 대응할 때 방어적인 자세를 취하지 않았습니다. 결국, 어린 시절 grep foo file.txt | cut ... | cut ...에는 자주 싱글을 할 때마다 grep파일 인수의 위치를 ​​배우고 첫 번째는 패턴이고 이후의 것은 파일 이름이라는 것을 알기 때문에 명령을 작성했을 것입니다.

cat내가 질문에 대답 할 때 사용하는 것은 의식적인 선택이었습니다. 부분적으로는 "좋은 맛"(Linus Torvalds의 말에서)의 이유 때문 이었지만 주로 기능적인 이유 때문이었습니다.

후자의 이유가 더 중요하므로 먼저 설명하겠습니다. 파이프 라인을 솔루션으로 제공 할 때 재사용이 가능할 것으로 기대합니다. 파이프 라인이 끝에 추가되거나 다른 파이프 라인에 연결될 가능성이 높습니다. 이 경우 grep에 대한 파일 인수가 있으면 재사용 가능성이 떨어지며 파일 인수가 있으면 오류 메시지없이 조용히 그렇게 할 수 있습니다. I. e. 및을 모두 포함하는 줄 수를 예상하는 동안 포함 된 grep foo xyz | grep bar xyz | wc줄 수를 제공합니다 . 파이프 라인에서 명령을 사용하기 전에 인수를 변경해야하는 경우 오류가 발생하기 쉽습니다. 여기에 조용한 실패의 가능성을 더하면 특히 교활한 관행이됩니다.xyzbarfoobar

전자의 이유도 중요하지 않습니다. 많은 " 좋은 취향 "은 교육을 필요로하는 누군가가 "하지만 그렇지 않다"고 말하는 순간에 당신이 옳게 생각할 수없는 위의 조용한 실패와 같은 것들에 대한 직관적 인 잠재 의식적 근거이기 때문입니다. 쓸모없는 그 고양이 ".

그러나 나는 또한 내가 언급 한 이전의 "좋은 맛"이유를 의식하도록 노력할 것이다. 그 이유는 유닉스의 직교 디자인 정신과 관련이 있습니다. grep하지 않습니다 cutls하지 않습니다 grep. 따라서 최소한 grep foo file1 file2 file3디자인 정신에 위배됩니다. 이를 수행하는 직교 방법은 cat file1 file2 file3 | grep foo. 이제는 grep foo file1의 특수한 경우 일 뿐이며 grep foo file1 file2 file3똑같이 치료하지 않으면 쓸모없는 고양이 상을 피하기 위해 적어도 뇌 시계주기를 사용하는 것입니다.

그것은 우리를 grep foo file1 file2 file3연결하고 cat연결 하는 논쟁으로 이끈다. 그래서 그것은 적절 cat file1 file2 file3하지만 cat연결되지 않기 cat file1 | grep foo때문에 우리는 cat전능 한 유닉스와 전능 한 유닉스 의 정신을 위반하고있다 . 글쎄, 만약 그렇다면 Unix는 한 파일의 출력을 읽고 stdout에 뱉어내는 다른 명령이 필요할 것입니다. (페이지를 매기거나 stdout에 대한 순수한 뱉는 것이 아닙니다). 그래서 당신은 당신이 말 cat file1 file2하거나 말하고 dog file1양심적으로 cat file1을 피하는 것을 피하는 것과 동시에 여러 파일이 지정된 경우 dog file1 file2의 디자인이 dog오류를 던질 것이기 때문에 피하는 상황 가질 것입니다.

바라건대,이 시점에서 여러분은 파일을 stdout에 뱉어내는 별도의 명령을 포함하지 cat않고 다른 이름을 지정 하는 대신 concatenate에 대한 이름 지정하는 Unix 설계자에게 공감합니다 . <edit>에 대한 잘못된 주석을 제거 <했습니다. 실제로 <파이프 라인의 시작 부분에 배치 할 수있는 stdout에 파일을 뱉어내는 효율적인 복사 금지 기능이므로 Unix 디자이너는이를 위해 특별히 뭔가를 포함했습니다.</edit>

다음 질문은 추가 처리없이 단순히 파일을 뱉거나 여러 파일을 stdout에 연결하는 명령을 갖는 것이 왜 중요합니까? 한 가지 이유는 표준 입력에서 작동하는 모든 단일 Unix 명령이 하나 이상의 명령 줄 파일 인수를 구문 분석하고 존재하는 경우 입력으로 사용하는 방법을 알지 못하도록하는 것입니다. 두 번째 이유는 사용자가 기억해야하는 것을 피하는 것입니다. (a) 파일 이름 인수가가는 위치; (b) 위에서 언급 한 자동 파이프 라인 버그를 피하십시오.

그것은 왜 grep추가 논리가 있는지 우리에게 가져옵니다 . 그 이유는 파이프 라인이 아닌 독립 실행 형 기반으로 자주 사용되는 명령에 대한 사용자 유창성을 허용 하는 것입니다. 유용성을 크게 높이기 위해 직교성을 약간 타협 한 것입니다. 모든 명령이 이러한 방식으로 설계되어야하는 것은 아니며 자주 사용되지 않는 명령은 파일 인수의 추가 논리를 완전히 피해야합니다 (추가 논리는 불필요한 취약성을 유발 (버그 가능성)). 예외는의 경우와 같은 파일 인수를 허용하는 것입니다 grep. (그런데, ls받아들이는 것이 아니라 파일 인수를 요구하는 완전히 다른 이유가 있음에 유의하십시오 )

마지막으로, 파일 인수가 지정 될 때 표준 입력도 사용할 수있는 경우 grep(반드시 그런 것은 아님 ls) 예외적 인 명령 이 오류를 생성하는 경우 더 잘 할 수있었습니다 .


아니!

우선, 명령에서 리디렉션이 발생하는 위치는 중요하지 않습니다. 따라서 명령 왼쪽에 리디렉션이 마음에 들면 괜찮습니다.

< somefile command

와 같다

command < somefile

둘째, 파이프를 사용할 때 n + 1 프로세스와 서브 쉘이 발생합니다. 확실히 느립니다. 어떤 경우에는 n 이 0이되었을 것입니다 (예를 들어 쉘 내장으로 리디렉션 할 때). 따라서를 사용 cat하면 완전히 불필요하게 새 프로세스를 추가하게됩니다.

일반화로 파이프를 사용할 때마다 제거 할 수 있는지 확인하는 데 30 초가 걸립니다. (하지만 아마도 30 초 이상 걸리지 않을 것입니다.) 다음은 파이프와 프로세스가 불필요하게 자주 사용되는 몇 가지 예입니다.

for word in $(cat somefile); … # for word in $(<somefile); … (or better yet, while read < somefile)

grep something | awk stuff; # awk '/something/ stuff' (similar for sed)

echo something | command; # command <<< something (although echo would be necessary for pure POSIX)

더 많은 예제를 추가하려면 자유롭게 편집하십시오.


UUoC 버전에서는 cat파일을 메모리로 읽어 들인 다음 파이프에 써야하며 명령은 파이프에서 데이터를 읽어야하므로 커널은 전체 파일을 복사 해야하는 반면 리디렉션 된 경우에는 커널은 파일을 한 번만 복사하면됩니다. 세 번하는 것보다 한 번하는 것이 더 빠릅니다.

사용 :

cat "$@" | command

는 완전히 다르며 cat. 명령이 0 개 이상의 파일 이름 인수를 받아들이고 차례로 처리하는 표준 필터 인 경우에는 여전히 쓸모가 없습니다. tr명령을 고려하십시오 . 파일 이름 인수를 무시하거나 거부하는 순수 필터입니다. 여러 파일을 피드하려면 cat표시된대로 사용해야 합니다. (물론의 설계 tr가별로 좋지 않다는 별도의 논의가 있습니다. 표준 필터로 설계 할 수 없었던 실제 이유는 없습니다.) 명령이 모든 입력을 다음과 같이 처리하도록하려는 경우에도 유효 할 수 있습니다. 명령이 여러 개의 개별 파일을 허용하더라도 여러 개의 개별 파일이 아닌 단일 파일입니다. 예를 들어, wc이러한 명령입니다.

그것은이다 cat single-file무조건 쓸모없는 경우.


다른 사람을 가르 칠 때 cat문제 나 작업에 적합한 출력을 생성하는 명령의 복잡한 파이프 라인이나 명령에 대한 편리한 자리 표시 자 이기 때문에 지나치게 잘난 척하는 UUOC Award의 대부분의 경우에 동의하지 않습니다.

이는 특히 Stack Overflow, ServerFault, Unix 및 Linux 또는 모든 SE 사이트와 같은 사이트에서 해당됩니다.

누군가 최적화에 대해 구체적으로 질문하거나 이에 대한 추가 정보를 추가하고 싶은 경우 고양이를 사용하는 것이 비효율적 인 방법에 대해 이야기하십시오. 그러나 사람들이보기보다 단순함과 이해의 용이성을 목표로 선택했기 때문에 사람들을 꾸짖지 마십시오! 복잡성.

요컨대, 고양이가 항상 고양이는 아니기 때문입니다.

또한 UUOC를 수여하는 것을 즐기는 대부분의 사람들은 사람들을 돕거나 가르치는 것보다 자신이 얼마나 '영리한지'를 과시하는 데 더 관심이 있기 때문에 그렇게합니다. 실제로, 그들은 동료를 이길 작은 막대기를 찾은 또 다른 초보자 일 것입니다.


최신 정보

https://unix.stackexchange.com/a/301194/7696에 답변에 게시 한 또 다른 UUOC가 있습니다 .

sqlq() {
  local filter
  filter='cat'

  # very primitive, use getopts for real option handling.
  if [ "$1" == "--delete-blank-lines" ] ; then
    filter='grep -v "^$"'
    shift
  fi

  # each arg is piped into sqlplus as a separate command
  printf "%s\n" "$@" | sqlplus -S sss/eee@sid | $filter
}

UUOC pedants는 이것이 UUOC라고 말할 것입니다. 왜냐하면 $filter빈 문자열에 대한 기본값을 쉽게 만들 수 있고 if명령문은 filter='| grep -v "^$"'IMO에 파이프 문자를 삽입하지 않음으로써 가능하기 때문입니다 $filter.이 "쓸모없는" cat은 사실을 자체 문서화하는 매우 유용한 목적을 제공합니다. 이 라인은 $filter에 대한 printf또 다른 인수가 아니라 sqlplus사용자가 선택할 수있는 선택적 출력 필터입니다.

여러 옵션 출력 필터를 할 필요가 있다면, 옵션 처리는 APPEND 수 | whatever$filter자주 필요 - 하나 개의 여분의 cat파이프 라인은 상처 아무것도에가는 또는 성능에 띄는 손실이 발생하지 않습니다.


에서 방어 고양이 :

예,

   < input process > output 

또는

   process < input > output 

더 효율적이지만 많은 호출에 성능 문제가 없으므로 상관하지 않습니다.

인체 공학적 이유 :

우리는 왼쪽에서 오른쪽으로 읽는 데 익숙하므로 다음과 같은 명령

    cat infile | process1 | process2 > outfile

이해하기 쉽지 않습니다.

    process1 < infile | process2 > outfile

process1을 건너 뛰고 왼쪽에서 오른쪽으로 읽어야합니다. 다음과 같은 방법으로 치료할 수 있습니다.

    < infile process1 | process2 > outfile

아무 것도없는 왼쪽을 가리키는 화살표가있는 것처럼 보입니다. 더 혼란스럽고 멋진 인용구처럼 보입니다.

    process1 > outfile < infile

스크립트 생성은 종종 반복적 인 프로세스입니다.

    cat file 
    cat file | process1
    cat file | process1 | process2 
    cat file | process1 | process2 > outfile

단계적으로 진행 상황을 볼 수있는 반면

    < file 

작동하지 않습니다. 간단한 방법은 오류 발생 가능성이 적고 인체 공학적 명령 catenation은 cat으로 간단합니다.

또 다른 주제는 대부분의 사람들이 컴퓨터를 사용하기 훨씬 전부터 프로그래머로 컴퓨터를 사용할 때 비교 연산자로> 및 <에 노출 된 경우가 훨씬 더 많다는 것입니다.

두 피연산자를 <및>와 비교하는 것은 반대 교환 적입니다.

(a > b) == (b < a)

입력 리디렉션에 <를 처음 사용했을 때를 기억합니다.

a.sh < file 

다음과 같을 수 있습니다

file > a.sh

어떻게 든 내 a.sh 스크립트를 덮어 씁니다. 아마도 이것은 많은 초보자에게 문제가 될 것입니다.

드문 차이

wc -c journal.txt
15666 journal.txt
cat journal.txt | wc -c 
15666

후자는 계산에 직접 사용할 수 있습니다.

factor $(cat journal.txt | wc -c)

물론 여기에서도 파일 매개 변수 대신 <를 사용할 수 있습니다.

< journal.txt wc -c 
15666
wc -c < journal.txt
15666

하지만 누가 신경 쓰나요-15k?

가끔 문제가 생기면 고양이를 부르는 습관을 바꿀 것입니다.

매우 크거나 많은 파일을 사용할 때 cat을 피하는 것이 좋습니다. 대부분의 질문에 고양이의 사용은 직교 적이며 주제에서 벗어난 것이지 문제가 아닙니다.

매 두 번째 셸 주제에 대해 쓸데없는 쓸모없는 고양이 토론을 시작하는 것은 성 가시고 지루할뿐입니다. 성능 문제를 다룰 때 인생을 얻고 명성의 순간을 기다리십시오.


추가 문제는 파이프가 서브 쉘을 조용히 마스킹 할 수 있다는 것입니다. 이 예를 들어, 내가 대체거야 cat와 함께 echo,하지만 같은 문제가 존재한다.

echo "foo" | while read line; do
    x=$line
done

echo "$x"

x을 포함 할 것으로 예상 foo있지만 그렇지 않습니다. x서브 쉘이 실행 양산에 당신을 설정했다 while루프를. x파이프 라인을 시작한 셸에서 관련없는 값이 있거나 전혀 설정되지 않았습니다.

bash4에서는 파이프 라인의 마지막 명령이 파이프 라인을 시작하는 것과 동일한 셸에서 실행되도록 몇 가지 셸 옵션을 구성 할 수 있지만 다음을 시도해 볼 수 있습니다.

echo "foo" | while read line; do
    x=$line
done | awk '...'

그리고 x다시 한 번에 로컬 while의 서브 쉘.


이것을 정기적으로 지적하는 사람과 다른 여러 쉘 프로그래밍 안티 패턴을 지적하는 사람으로서, 나는 뒤늦게도 무게를 잴 의무가 있다고 느낍니다.

쉘 스크립트는 복사 / 붙여 넣기 언어입니다. 쉘 스크립트를 작성하는 대부분의 사람들은 언어를 배우기위한 것이 아닙니다. 그것은 그들이 실제로 어느 정도 익숙한 언어로 일을 계속하기 위해 극복해야하는 장애물 일뿐입니다.

그런 맥락에서 다양한 쉘 스크립팅 안티 패턴을 전파하는 것이 파괴적이고 잠재적으로 파괴적이라고 생각합니다. 누군가가 Stack Overflow에서 찾은 코드는 최소한의 변경과 불완전한 이해로 환경에 복사 / 붙여 넣기가 가능해야합니다.

넷상의 많은 셸 스크립팅 리소스 중에서 Stack Overflow는 사용자가 사이트의 질문과 답변을 편집하여 사이트의 품질을 형성하는 데 도움을 줄 수 있다는 점에서 특이합니다. 그러나 코드 작성자가 의도하지 않은 변경 작업을 수행하기 쉽기 때문에 코드 편집이 문제가 될 수 있습니다 . 따라서 우리는 코드 변경을 제안하기 위해 주석을 남기는 경향이 있습니다.

UUCA 및 관련 반 패턴 주석은 우리가 주석을다는 코드 작성자만을위한 것이 아닙니다. 그들은 많이 있습니다 주의의 위험 부담 도움말에 독자 들은 여기서 찾을 코드에서 문제를 인식하게 사이트.

Stack Overflow에 대한 답변이 쓸모없는 cats (또는 인용되지 않은 변수, 또는 chmod 777매우 다양한 기타 반 패턴 재앙)를 권장하지 않는 상황을 달성하고 싶지는 않지만 최소한 복사하려는 사용자를 교육 할 수 있습니다. 이 코드를 수백만 번 실행되는 스크립트의 가장 꽉 찬 루프에 붙여 넣습니다.

기술적 이유에 관한 한, 전통적인 통념은 우리가 외부 프로세스의 수를 최소화하려고 노력해야한다는 것입니다. 이것은 쉘 스크립트를 작성할 때 좋은 일반 지침으로 계속 유지됩니다.


나는 종종 cat file | myprogram예에서 사용 합니다. 때때로 나는 고양이의 쓸모없는 사용으로 비난 받고 있습니다 ( http://porkmail.org/era/unix/award.html ). 다음과 같은 이유로 동의하지 않습니다.

  • 무슨 일이 일어나고 있는지 이해하기 쉽습니다.

    UNIX 명령을 읽을 때 명령과 인수, 리디렉션이 예상됩니다. 어디에서나 리디렉션을 넣을 수 있지만 거의 보이지 않으므로 사람들은 예제를 읽는 데 더 어려움을 겪을 것입니다. 나는 믿는다

    cat foo | program1 -o option -b option | program2
    

    보다 읽기 쉽다

    program1 -o option -b option < foo | program2
    

    리디렉션을 처음으로 이동하면이 구문에 익숙하지 않은 사람들을 혼란스럽게합니다.

    < foo program1 -o option -b option | program2
    

    예는 이해하기 쉬워야합니다.

  • 변경하기 쉽습니다.

    프로그램이에서 읽을 수 있다는 것을 알고 있으면 cat일반적으로 STDOUT으로 출력하는 모든 프로그램의 출력을 읽을 수 있다고 가정 할 수 있으므로 필요에 맞게 조정하고 예측 가능한 결과를 얻을 수 있습니다.

  • STDIN이 파일이 아닌 경우 프로그램이 실패하지 않는다는 점을 강조합니다.

    program1 < foo작동 하면 작동 할 것이라고 가정하는 것은 안전하지 않습니다 cat foo | program1. 그러나 그 반대를 가정하는 것이 안전합니다. 이 프로그램은 STDIN이 파일이면 작동하지만 입력이 파이프이면 실패합니다.

    # works
    < foo perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    
    # fails
    cat foo | perl -e 'seek(STDIN,1,1) || die;print <STDIN>'
    

성능 비용

추가를 수행하는 데 드는 비용이 있습니다 cat. 기준선 ( cat), 낮은 처리량 ( bzip2), 중간 처리량 ( gzip) 및 높은 처리량 ( grep) 을 시뮬레이션하기 위해 몇 가지 테스트를 얼마나 많이 실행했는지 알 수 있습니다.

cat $ISO | cat
< $ISO cat
cat $ISO | bzip2
< $ISO | bzip2
cat $ISO | gzip
< $ISO gzip
cat $ISO | grep no_such_string
< $ISO grep no_such_string

테스트는 로우 엔드 시스템 (0.6GHz)과 일반 노트북 (2.2GHz)에서 실행되었습니다. 각 시스템에서 10 번 실행되었으며 각 테스트의 최적 상황을 모방하기 위해 최적의 타이밍이 선택되었습니다. $ ISO는 ubuntu-11.04-desktop-i386.iso입니다. (예쁜 테이블 : http://oletange.blogspot.com/2013/10/useless-use-of-cat.html )

CPU                       0.6 GHz ARM
Command                   cat $ISO|                        <$ISO                            Diff                             Diff (pct)
Throughput \ Time (ms)    User       Sys        Real       User       Sys        Real       User       Sys        Real       User       Sys        Real
Baseline (cat)                     55      14453      33090         23       6937      33126         32       7516        -36        239        208         99
Low (bzip2)                   1945148      16094    1973754    1941727       5664    1959982       3420      10430      13772        100        284        100
Medium (gzip)                  413914      13383     431812     407016       5477     416760       6898       7906      15052        101        244        103
High (grep no_such_string)      80656      15133      99049      79180       4336      86885       1476      10797      12164        101        349        114

CPU                       Core i7 2.2 GHz
Command                   cat $ISO|           <$ISO             Diff          Diff (pct)
Throughput \ Time (ms)    User     Sys Real   User   Sys Real   User Sys Real User       Sys Real
Baseline (cat)                    0 356    215      1  84     88    0 272  127          0 423  244
Low (bzip2)                  136184 896 136765 136728 160 137131 -545 736 -366         99 560   99
Medium (gzip)                 26564 788  26791  26332 108  26492  232 680  298        100 729  101
High (grep no_such_string)      264 392    483    216  84    304   48 308  179        122 466  158

결과는 처리량이 낮거나 중간 인 경우 비용이 1 % 정도임을 보여줍니다. 이것은 측정의 불확실성 범위 내에 있으므로 실제로 차이가 없습니다.

높은 처리량의 경우 차이가 더 크고 둘 사이에 분명한 차이가 있습니다.

결론은 다음과 같습니다. 다음 <과 같은 cat |경우 대신 사용해야 합니다.

  • 처리의 복잡성은 단순한 grep과 유사합니다.
  • 성능은 가독성보다 중요합니다.

그렇지 않으면 <또는 을 사용하는지 여부는 중요하지 않습니다 cat |.

따라서 다음과 같은 경우에만 UUoC 보상을 제공해야합니다.

  • 성과의 상당한 차이를 측정 할 수 있습니다 (상을 수여 할 때 측정치를 게시)
  • 성능은 가독성보다 중요합니다.

나는 (전통적인 방법) 파이프를 사용하는 것이 조금 더 빠르다고 생각합니다. 내 상자에서 나는 strace무슨 일이 일어나고 있는지 확인하기 위해 명령을 사용 했습니다.

파이프없이 :

toc@UnixServer:~$ strace wc -l < wrong_output.c
execve("/usr/bin/wc", ["wc", "-l"], [/* 18 vars */]) = 0
brk(0)                                  = 0x8b50000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ad000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=29107, ...}) = 0
mmap2(NULL, 29107, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77a5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1552584, ...}) = 0
mmap2(NULL, 1563160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7627000
mmap2(0xb779f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x178) = 0xb779f000
mmap2(0xb77a2000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb77a2000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7626000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb76268d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb779f000, 8192, PROT_READ)   = 0
mprotect(0x804f000, 4096, PROT_READ)    = 0
mprotect(0xb77ce000, 4096, PROT_READ)   = 0
munmap(0xb77a5000, 29107)               = 0
brk(0)                                  = 0x8b50000
brk(0x8b71000)                          = 0x8b71000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=5540198, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7426000
mmap2(NULL, 1507328, PROT_READ, MAP_PRIVATE, 3, 0x2a8) = 0xb72b6000
close(3)                                = 0
open("/usr/share/locale/locale.alias", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ac000
read(3, "# Locale name alias data base.\n#"..., 4096) = 2570
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb77ac000, 4096)                = 0
open("/usr/share/locale/fr_FR.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr_FR.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr_FR/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/fr/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr_FR/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale-langpack/fr/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=316721, ...}) = 0
mmap2(NULL, 316721, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7268000
close(3)                                = 0
open("/usr/lib/i386-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=26064, ...}) = 0
mmap2(NULL, 26064, PROT_READ, MAP_SHARED, 3, 0) = 0xb7261000
close(3)                                = 0
read(0, "#include<stdio.h>\n\nint main(int "..., 16384) = 180
read(0, "", 16384)                      = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7260000
write(1, "13\n", 313
)                     = 3
close(0)                                = 0
close(1)                                = 0
munmap(0xb7260000, 4096)                = 0
close(2)                                = 0
exit_group(0)                           = ?

그리고 파이프 :

toc@UnixServer:~$ strace cat wrong_output.c | wc -l
execve("/bin/cat", ["cat", "wrong_output.c"], [/* 18 vars */]) = 0
brk(0)                                  = 0xa017000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb774b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=29107, ...}) = 0
mmap2(NULL, 29107, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7743000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1552584, ...}) = 0
mmap2(NULL, 1563160, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75c5000
mmap2(0xb773d000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x178) = 0xb773d000
mmap2(0xb7740000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7740000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75c4000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75c48d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb773d000, 8192, PROT_READ)   = 0
mprotect(0x8051000, 4096, PROT_READ)    = 0
mprotect(0xb776c000, 4096, PROT_READ)   = 0
munmap(0xb7743000, 29107)               = 0
brk(0)                                  = 0xa017000
brk(0xa038000)                          = 0xa038000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=5540198, ...}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb73c4000
mmap2(NULL, 1507328, PROT_READ, MAP_PRIVATE, 3, 0x2a8) = 0xb7254000
close(3)                                = 0
fstat64(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
open("wrong_output.c", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0664, st_size=180, ...}) = 0
read(3, "#include<stdio.h>\n\nint main(int "..., 32768) = 180
write(1, "#include<stdio.h>\n\nint main(int "..., 180) = 180
read(3, "", 32768)                      = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
13

좋은 벤치마킹을 위해 점점 더 긴 명령 으로 stracetime명령을 사용하여 테스트를 수행 할 수 있습니다 .

참고 URL : https://stackoverflow.com/questions/11710552/useless-use-of-cat

반응형