뇌 마음 반반저장소

[42_pipex] 탐구1. pipex 구조 자세히 살펴보기 및 예제 본문

42/pipex

[42_pipex] 탐구1. pipex 구조 자세히 살펴보기 및 예제

맹진저 2023. 1. 5. 21:38
728x90

pipe란 뭔가요?

이 서브젝트를 이해하기 위해서는 일단 pipe(|)가 shell에서 어떤 역할을 하는지 알아야만 한다.

 

파이프는 말 그대로 걸러주는 망이 있는 배관이라고 생각하면 된다. 

pipe 명령어의 실행과정

1. ls 명령어를 통해 현재 폴더에 A.c, B.h, C.txt라는 파일이 있는 것을 확인하고

2. | 를 통해서 걸러주는데

3. grep을 통해서 c파일만 잡아와라

 

결과는?

$ ls | grep *.c
> A.c

 


 

서브젝트에 있는 예제 확인해 보기

$ < infile grep a1 | wc -w > outfile

일단 꺽쇠가 두 개가 있고.. 파일이 두개가 있고.. 명령어가 두개가 있고.. 파이프가 하나 있다.. 파이프의 역할은 알았으니 꺽쇠의 역할을 알아보자!

1. 리디렉션(Redirection Operator) : >, >> (Greater than) <, << (Less than)

리다이렉션은 말 그대로 방향을 바꾸어 주는 것이다.

 

1. 먼저 ">" 이 친구는 덮어써주는 역할을 한다.

$ ls > outfile

위의 뜻은 ls의 결과를 outfile에 덮어 쓰라는 뜻이다!

$ cat outfile 
A.c
B.h
C.txt
outfile

 

2. 만약 ">>" 꺽쇠가 이렇게 두 개가 있다면? 파일 끝에 추가해 준다.

ls -l >> outfile

문서 끝 부분부터 데이터를 덧붙인 다는 뜻이다!

$ cat outfile 
A.c
B.h
C.txt
outfile
total 0
-rwxrwxrwx 1 myID myID  0 Jan  4 10:41 A.c
-rwxrwxrwx 1 myID myID  0 Jan  4 10:41 B.h
-rwxrwxrwx 1 myID myID  0 Jan  4 10:41 C.txt
-rwxrwxrwx 1 myID myID 22 Jan  4 10:42 outfile

 

3. 그렇다면 다른 방향인 "<" 이 친구는? 가장 헷갈렸던 부분이다. 그냥 꺽쇠 방향만 바꿨을 뿐, 일을 수행해주는 것은 같다! 참 쉽쥬? 아래의 예를 보자. 파일(뒤를)을 기준으로 반대로 생각하면 된다.

$ grep A < outfile

이 예시는 이렇게 설명할 수 있다. outfile에서 A가 나오는 것을 잡아라! 결과는?

A.c
-rwxrwxrwx 1 myID myID  0 Jan  4 10:41 A.c

 

4. 자 그러면 < 와 >를 같이 사용하면 어떻게 될까?

$ grep A < infile > outfile

infile 내용에서 A를 다 잡아서 outfile에 모두 저장해라 라는 뜻이다! 

 

다양한 쉘 스크립트의 명령어를 잘 설명해놓은 페이지를 찾아 아래에 공유한다. 👇

 


 

2. 0, 1, 2... 표준 입력(stdin)과 표준 출력(stdout), 표준 에러(stderr) 예제

입출력의 과정을 그림으로 그려봤다. 입력장치로 명령어를 입력하면 정상 출력되거나 에러가 일어나는 두 가지 경우의 수가 있다. 

컴퓨터의 배설(?)구조

기본적으로 stdin은 0, stdout은 1, stderr는 2라고 약속했다. 그래서 파일스크립터로 코딩을 할 때도 3개의 숫자는 제외하고 항상 3부터 시작한다.


!추가자료 STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO!

파일 디스크립터의 I/O 번호와 상수이름👇

파일 I/O에 관한 리눅스 시스템 호출로 파일을 열어 데이터를 쓰거나 파일의 내용을 읽어오는 등의 작업을 할 수 있습니다. 대표적인 파일 I/O에 사용하는 시스템 호출에는 open, close, read, write, lseek 함수가 있습니다.

리눅스 시스템에서는 프로세스가 파일 입출력을 위해 열려진 파일마다 파일 기술자(fd)를 참조합니다. 프로세스가 open 함수를 호출하면 리눅스 시스템의 커널에서는 기존의 파일을 열거나 새로운 파일을 생성하여 파일 기술자를 반환합니다. 파일 기술자는 부호가 없는 정수로 하나의 프로세스에서 파일 입출력을 수행하는 단위마다 유일한 번호를 보장합니다.

특히 리눅스 쉘에 동작하는 프로세스는 개발자 코드가 아닌 프로세스 형성 과정에서 표준 입력과 표준 출력, 표준 에러 파일을 열어주며 이들의 파일 기술자는 0, 1, 2번입니다. 이는 unistd.h에 매크로 상수로 정의하고 있는데 이들 상수 이름은 STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO입니다.
#include <unistd.h>
#include <stdio.h>
#include <limits.h>

int main()
{
    printf("STDIN_FILENO:%u\n",STDIN_FILENO);
    printf("STDOUT_FILENO:%u\n",STDOUT_FILENO);
    printf("STDERR_FILENO:%u\n",STDERR_FILENO);
    printf("FOPEN_MAX:%u\n",FOPEN_MAX);
    return 0;
}
STDIN_FILENO: 0
STDOUT_FILENO: 1
STDERR_FILENO: 2
FOPEN_MAX: 16

출처 : https://ehpub.co.kr/tag/stdin_fileno/


stdin과 stdin_fileno의 차이점👇

stdin 타입은 file*이고, Stdin_fileno 타입은 int이다.

The functions that use stdin are mainly: Fread, fwrite, fclose, and so on, basically beginning with F. Functions that use Stdin_fileno are: Read, write, close, etc.
stdin을 사용하는 함수는 주로 Fread, fwrite, fclose 등이며 기본적으로 F부터 시작합니다. Stdin_fileno를 사용하는 함수는 Read, write, close 등입니다.

The file APIs provided at the operating system level represent files in file descriptors. Stdin_fileno is the file descriptor for the standard input device (typically the keyboard).
운영 체제 수준에서 제공되는 파일 API는 파일 설명자의 파일을 나타냅니다. Stdin_fileno는 표준 입력 장치(일반적으로 키보드)의 파일 설명자입니다.
Standard C + + at the level of the file Operations function libraries are used file* to represent the file, stdin is to point to the standard input device file file*.
파일 수준의 표준 C++ 작업 함수 라이브러리는 file*을 사용하여 파일을 나타내고 stdin은 표준 입력 장치 파일 file*을 가리킵니다.

출처 : The difference between Stdin,stdout,stderr and Stdin_fileno,stdout_fileno,stderr_fileno?

 

STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO은 변수로 사용가능할까?👇

아래의 포스팅 dup, dup2에서 계속..

[42_pipex] 함수2. dup, dup2, execve, access, unlink 자세한 설명

 


 

위의 과정을 직접 실습해볼 좋은 사이트를 찾아서 아래와 같이 수행해 보았다.

What Are stdin, stdout, and stderr on Linux? - DAVE MCKAY

!실습하기!

vim에 이렇게 입력한다.

$ vim error.sh
#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

그리고 접근권한을 수정해 사용가능하게 설정한다.

$ chmod +x error.sh

쉘 스크립트를 실행해 보자.

$ ./error.sh
About to try to access a file that doesn't exist
cat: bad-filename.txt: No such file or directory

error.sh을 capture.txt라는 새로운 파일에 출력해 보자.

$ ./error.sh > capture.txt
cat: bad-filename.txt: No such file or directory

bad-filename.txt는 여전히 파일이 없기 때문에 오류 메시지가 뜬다.

 

그러면 stdout의 출력이 파일로 갔는지 확인해 보자.

$ cat capture.txt
About to try to access a file that doesn't exist

stdin의 출력이 주어진 방향으로 잘 들어간 것이 보인다.

 

그러면 stdout과 stderr를 구분해서 출력하려면 어떻게 하면 될까? 다른 텍스트 파일에 만들어보자.

-stdout 출력하기

1>
$ ./error.sh 1> stdout_1.txt
cat: bad-filename.txt: No such file or directory #남은 텍스트 출력
$ cat stdout_1.txt       
About to try to access a file that doesn't exist

stdout의 정상출력 값으로 메시지가 들어간다.!

 

-stderr 출력하기

2>
$ ./error.sh 2> stderr_2.txt
About to try to access a file that doesn't exist #남은 텍스트 출력
$ cat stderr_2.txt       
cat: bad-filename.txt: No such file or directory

stderr의 에러메시지가 값으로 들어간다!

 

-둘 다 출력하기

$ ./error.sh 1> stdout.txt 2> strerr.txt

두 라인 모두 파일로 들어갔으므로 남은 라인이 없다.

$ cat stdout.txt 
About to try to access a file that doesn't exist
$ cat stderr.txt
cat: stderr.txt: No such file or directory

 

PIPEX의 기본 구조

그렇다면 위의 리서치에 기반해 우리가 만들어야 할 셸 명령어를 분석해 보자.

Pipex 명령어 원본 구조 이해하기

일단 infile에 이렇게 넣었다.

$ cat infile 
Hello
World
a1
I'm
baby
developper
a1

자 그럼 아래 명령어를 해석해보자.

< infile grep a1 | wc -w > outfile

1. infile 속에 a1을 잡아라.

2. 이 결과 값에서 결과의 수는?

3. outfile에 결과값을 저장할것.

 

outfile의 결과는?

$ cat outfile
2

 

Pipex의 해석은 이렇게 할 수 있겠다.

pipex 명령어의 구조

 

728x90
Comments