development

Bash에서 파이프가 작동하는 방식에 대한 간단한 설명은 무엇입니까?

big-blog 2020. 12. 11. 19:05
반응형

Bash에서 파이프가 작동하는 방식에 대한 간단한 설명은 무엇입니까?


나는 종종 Bash에서 파이프를 사용합니다.

dmesg | less

이 출력이 무엇인지 알고 있지만을 dmesg사용하여 스크롤 할 수 less있지만 |이 작업이 무엇인지 이해하지 못합니다 . 단순히 반대 >입니까?

  • 무엇을하는지에 대한 간단하거나 은유적인 설명 |이 있습니까?
  • 한 줄에 여러 개의 파이프를 사용하면 어떻게됩니까?
  • 파이프의 동작이 Bash 스크립트에 나타나는 모든 곳에서 일관됩니까?

Unix 파이프는 첫 번째 프로세스의 STDOUT (표준 출력) 파일 설명자를 두 번째 프로세스의 STDIN (표준 입력)에 연결합니다. 그러면 첫 번째 프로세스가 STDOUT에 쓸 때 두 번째 프로세스가 출력을 즉시 읽을 수 있습니다 (STDIN에서).

여러 파이프를 사용하는 것은 단일 파이프를 사용하는 것과 다르지 않습니다. 각 파이프는 독립적이며 인접한 프로세스의 STDOUT 및 STDIN을 간단히 연결합니다.

세 번째 질문은 약간 모호합니다. 예, 파이프는 bash 스크립트의 모든 곳에서 일관됩니다. 그러나 파이프 문자 |는 다른 것을 나타낼 수 있습니다. 이중 파이프 ( ||)는 예를 들어 "or"연산자를 나타냅니다.


Linux (및 일반적으로 Unix)에서 각 프로세스에는 세 가지 기본 파일 설명자가 있습니다.

  1. fd # 0 프로세스의 표준 입력을 나타냅니다.
  2. fd # 1은 프로세스의 표준 출력을 나타냅니다.
  3. fd # 2는 프로세스의 표준 오류 출력을 나타냅니다.

일반적으로 간단한 프로그램을 실행할 때 이러한 파일 설명자는 기본적으로 다음과 같이 구성됩니다.

  1. 기본 입력은 키보드에서 읽습니다.
  2. 표준 출력은 모니터로 구성됩니다.
  3. 표준 오류도 모니터로 구성됩니다.

Bash는이 동작을 변경하기 위해 여러 연산자를 제공합니다 (예 :>, >> 및 <연산자를 살펴보십시오). 따라서 출력을 표준 출력이 아닌 다른 것으로 리디렉션하거나 키보드가 아닌 다른 스트림에서 입력을 읽을 수 있습니다. 두 프로그램이 다른 프로그램의 출력을 입력으로 사용하는 방식으로 공동 작업 하는 경우 특히 흥미 롭습니다 . 이러한 협업을 쉽게하기 위해 Bash는 파이프 운영자를 제공합니다 |. 연결 대신 공동 작업의 사용에 유의하십시오 . 실제로 파이프 는 순차적이지 않기 때문에이 용어의 사용을 피했습니다 . 파이프가있는 일반 명령 줄에는 다음과 같은 측면이 있습니다.

    > program_1 | program_2 | ... | program_n

위의 명령 줄은 약간 오해의 소지가 있습니다. 사용자는 program_1이 실행을 마치면 program_2가 입력을받는다고 생각할 수 있습니다. 이는 올바르지 않습니다. 사실, bash는 모든 프로그램을 병렬 로 시작 하고 그에 따라 입력 출력을 구성하여 모든 프로그램이 이전 프로그램에서 입력을 가져와 다음 출력으로 전달합니다 (명령 줄에서 설정된 순서대로).

다음은 상위 프로세스와 하위 프로세스 사이에 파이프를 생성하는 C파이프 생성 의 간단한 예입니다 . 중요한 부분은 pipe ()에 대한 호출과 부모가 fd 1을 닫는 방법 (쓰기 쪽)과 자식이 fd 1을 닫는 방법 (쓰기 쪽)입니다. 파이프는 단방향 통신 채널입니다. 따라서 데이터는 한 방향으로 만 흐를 수 있습니다. fd 1 은 fd [0]을 향합니다. 더 많은 정보는 pipe ()의 매뉴얼 페이지를보세요.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
    int     fd[2], nbytes;
    pid_t   childpid;
    char    string[] = "Hello, world!\n";
    char    readbuffer[80];

    pipe(fd);

    if((childpid = fork()) == -1)
    {
            perror("fork");
            exit(1);
    }

    if(childpid == 0)
    {
            /* Child process closes up input side of pipe */
            close(fd[0]);

            /* Send "string" through the output side of pipe */
            write(fd[1], string, (strlen(string)+1));
            exit(0);
    }
    else
    {
            /* Parent process closes up output side of pipe */
            close(fd[1]);

            /* Read in a string from the pipe */
            nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
            printf("Received string: %s", readbuffer);
    }

    return(0);
}

마지막으로 다음과 같은 형식의 명령 줄이 있습니다.

> program_1 | program_2 | program_3

The return code of the whole line is set to the last command. In this case program_3. If you would like to get an intermediate return code you have to set the pipefail or get it from the PIPESTATUS.


Every standard process in Unix has at least three file descriptors, which are sort of like interfaces:

  • Standard output, which is the place where the process prints its data (most of the time the console, that is, your screen or terminal).
  • Standard input, which is the place it gets its data from (most of the time it may be something akin to your keyboard).
  • Standard error, which is the place where errors and sometimes other out-of-band data goes. It's not interesting right now because pipes don't normally deal with it.

The pipe connects the standard output of the process to the left to the standard input of the process of the right. You can think of it as a dedicated program that takes care of copying everything that one program prints, and feeding it to the next program (the one after the pipe symbol). It's not exactly that, but it's an adequate enough analogy.

Each pipe operates on exactly two things: the standard output coming from its left and the input stream expected at its right. Each of those could be attached to a single process or another bit of the pipeline, which is the case in a multi-pipe command line. But that's not relevant to the actual operation of the pipe; each pipe does its own.

The redirection operator (>) does something related, but simpler: by default it sends the standard output of a process directly to a file. As you can see it's not the opposite of a pipe, but actually complementary. The opposite of > is unsurprisingly <, which takes the content of a file and sends it to the standard input of a process (think of it as a program that reads a file byte by byte and types it in a process for you).


A pipe takes the output of a process, by output I mean the standard output (stdout on UNIX) and passes it on the standard input (stdin) of another process. It is not the opposite of the simple right redirection > which purpose is to redirect an output to another output.

For example, take the echo command on Linux which is simply printing a string passed in parameter on the standard output. If you use a simple redirect like :

echo "Hello world" > helloworld.txt

the shell will redirect the normal output initially intended to be on stdout and print it directly into the file helloworld.txt.

Now, take this example which involves the pipe :

ls -l | grep helloworld.txt

The standard output of the ls command will be outputed at the entry of grep, so how does this work?

Programs such as grep when they're being used without any arguments are simply reading and waiting for something to be passed on their standard input (stdin). When they catch something, like the ouput of the ls command, grep acts normally by finding an occurence of what you're searching for.


  • | puts the STDOUT of the command at left side to the STDIN of the command of right side.

  • If you use multiple pipes, it's just a chain of pipes. First commands output is set to second commands input. Second commands output is set to next commands input. An so on.

  • It's available in all Linux/widows based command interpreter.


The pipe operator takes the output of the first command, and 'pipes' it to the second one by connecting stdin and stdout. In your example, instead of the output of dmesg command going to stdout (and throwing it out on the console), it is going right into your next command.


Pipes are very simple like this.

You have the output of one command. You can provide this output as the input into another command using pipe. You can pipe as many commands as you want.

ex: ls | grep my | grep files

This first lists the files in the working directory. This output is checked by the grep command for the word "my". The output of this is now into the second grep command which finally searches for the word "files". Thats it.


If you treat each unix command as a standalone module,
but you need them to talk to each other using text as a consistent interface,
how can it be done?

cmd                       input                    output

echo "foobar"             string                   "foobar" 
cat "somefile.txt"        file                     *string inside the file*
grep "pattern" "a.txt"    pattern, input file      *matched string*

You can say | is a metaphor for passing the baton in a relay marathon.
Its even shaped like one!
cat -> echo -> less -> awk -> perl is analogous to cat | echo | less | awk | perl.

cat "somefile.txt" | echo
cat pass its output for echo to use.

What happens when there is more than one input?
cat "somefile.txt" | grep "pattern"
There is an implicit rule that says "pass it as input file rather than pattern" for grep.
You will slowly develop the eye for knowing which parameter is which by experience.

참고URL : https://stackoverflow.com/questions/9834086/what-is-a-simple-explanation-for-how-pipes-work-in-bash

반응형