일부 명령이 표준 입력에서 읽히지 않는 이유는 무엇입니까? grep pdf|

언제 파이프 라인을 사용해야하는지, 그렇지 않아야하는지 궁금합니다.

예를 들어 pdf 파일을 처리하는 특정 프로세스를 종료하려면 파이프 라인을 사용하여 다음을 수행 할 수 없습니다.

ps aux | grep pdf | awk '{print $2}'|kill

대신 다음과 같은 방법으로 만 할 수 있습니다.

kill $(ps aux| grep pdf| awk '{print $2}')

또는

ps aux | grep pdf | awk '{print $2}'| xargs kill

man bash(버전 4.1.2) 에 따르면 :

The standard output of command is connected via a pipe to the standard input of command2.

위 시나리오의 경우 :

  • 의 표준 입력 grep은의 표준 출력입니다 ps. 작동합니다.
  • 의 표준 입력 awk은의 표준 출력입니다 grep. 작동합니다.
  • 의 표준 입력 kill은의 표준 출력입니다 awk. 작동하지 않습니다.

다음 명령의 표준 입력은 항상 이전 명령의 표준 출력에서 ​​입력을받습니다.

  • kill또는 왜 작동하지 rm않습니까?
  • kill, rminput with grep, awkinput 의 차이점은 무엇입니까 ?
  • 규칙이 있습니까?


답변

프로그램에 입력을 제공하는 두 가지 일반적인 방법이 있습니다.

  • 프로세스의 STDIN에 데이터를 제공
  • 명령 행 인수 지정

kill명령 행 인수 만 사용합니다. STDIN에서 읽지 않습니다. STDIN grep과 유사 하고 awk읽은 프로그램 (파일 이름이 명령 행 인수로 제공되지 않은 경우) 및 명령 행 인수 (패턴, 명령문, 플래그 등)에 따라 데이터를 처리합니다.

명령 행 인수가 아닌 다른 프로세스의 STDIN에만 파이프 할 수 있습니다.

일반적인 규칙은 프로그램이 STDIN을 사용하여 임의의 양의 데이터를 처리하는 것입니다. 모든 추가 입력 매개 변수 또는 일반적으로 거의없는 경우 명령 행 인수에 의해 전달됩니다. 긴 awk프로그램 텍스트와 같이 명령 행이 매우 길어질 수있는 경우 추가 프로그램 파일에서 -f옵션 을 읽을 수 있습니다 ( 옵션 awk).

프로그램의 STDOUT을 명령 행 인수로 사용하려면 $(...)또는 많은 양의 데이터를 사용하십시오 xargs. find로 직접 할 수도 있습니다 -exec ... {} +.

완전성 : 명령 행 인수를 STDOUT에 쓰려면을 사용하십시오 echo.


답변

이것은 흥미로운 질문이며 유닉스 / 리눅스 철학의 일부를 다루고 있습니다.

따라서, 같은 프로그램의 차이는 무엇인가 grep, sed, sort그리고 한편으로 kill, rm, ls다른 한편으로는? 두 가지 측면이 있습니다.

필터 양태

  • 첫 번째 종류의 프로그램은 필터 라고도 합니다 . 파일 또는 STDIN에서 입력을 가져 와서 수정 한 후 주로 STDOUT에 대한 출력을 생성합니다. 소스 및 대상으로 다른 프로그램과 함께 파이프에 사용됩니다.

  • 두 번째 종류의 프로그램은 입력에 작용하지만, 그들이 제공하는 출력은 종종 입력과 관련이 없습니다. kill정기적으로 작동 할 때 출력이 없으며 둘 다 작동하지 않습니다 ls. 성공을 나타내는 반환 값만 있습니다. 일반적으로 STDIN에서 입력을받지는 않지만 대부분 STDOUT에 출력을 제공합니다.

와 같은 프로그램의 ls경우 필터 측면이 그다지 효과적이지 않습니다. 확실히 입력을 가질 수 있지만 (필요하지는 않음) 출력은 해당 입력과 밀접한 관련이 있지만 필터로 작동하지는 않습니다. 그러나 이러한 종류의 프로그램의 경우 다른 측면은 여전히 ​​작동합니다.

의미 양태

  • 필터의 경우 입력에 의미없습니다 . 그들은 단지 데이터를 읽고, 데이터를 수정하고, 데이터를 출력합니다. 이것이 숫자 값, 일부 파일 이름 또는 HTML 소스 코드 목록인지는 중요하지 않습니다. 이 데이터의 의미는 코드 만 주어진다 당신 의 정규식 : 필터에 제공 grep, 규칙 awk또는 펄 프로그램입니다.

  • 다른 프로그램의 경우처럼 killls자신의 입력은있다, 의미 하는 명시 적 의미를 . kill프로세스 번호, ls파일 또는 경로 이름이 필요합니다. 임의의 데이터를 처리 할 수 ​​없으며 의도하지 않습니다. 그들 중 대부분은와 같은 입력이나 매개 변수가 필요하지 않습니다 ps. 일반적으로 STDIN에서 읽지 않습니다.

아마도이 두 가지 측면을 결합 할 수있을 것입니다. 필터는 입력에 프로그램의 의미가없는 프로그램입니다.

나는이 철학에 대해 읽은 것이 확실하지만 현재 어떤 출처도 기억하지 못합니다. 미안합니다. 누군가가 소스를 가지고 있다면 자유롭게 편집하십시오.


답변

“규칙”은 없습니다. 일부 프로그램은 STDIN에서 입력을 받고 일부는 그렇지 않습니다. 프로그램이 STDIN에서 입력을받을 수있는 경우 파이프되지 않을 수 있습니다.

일반적으로 프로그램의 기능에 대해 생각하여 프로그램이 입력을 받을지 여부를 알 수 있습니다. 프로그램의 작업이 어떻게 든 조작하는 경우 내용을 파일 (예를 들어,의 grep, sed, awk등), 그것은 일반적으로 STDIN에서 입력을 받아. 그 작업이 파일 자체 (예를 들어 조작 할 경우 mv, rm, cp) 또는 프로세스 (예를 들어 kill, lsof) 또는 무언가에 대한 반환 정보에 (예 top, find, ps) 그것은하지 않습니다.

그것에 대해 생각하는 또 다른 방법은 인수와 입력의 차이입니다. 예를 들면 다음과 같습니다.

mv foo bar

위의 명령 mv에는 입력이 없습니다. 주어진 것은 두 가지 주장입니다. 파일 중 하나에있는 내용을 알거나 신경 쓰지 않으며, 그 파일이 인수라는 것을 알고 조작해야합니다.

반면에

sed -e 's/foo/bar/' < file
--- -- ------------   ----
 |   |       |          |-> input
 |   |       |------------> argument
 |   |--------------------> option/flag/switch
 |------------------------> command

여기 sed에는 인수뿐만 아니라 입력이 주어졌습니다. 입력이되므로 STDIN에서 읽어서 파이프 할 수 있습니다.

인수가 입력 이 때 더 복잡해집니다 . 예를 들어

cat file

여기 file에 주어진 인수가 cat있습니다. 정확하게 말하면 파일 이름 file 이 인수입니다. 그러나 cat파일의 내용을 조작하는 프로그램이므로 입력 내용은 내부에 file있습니다.

strace프로세스에서 수행 한 시스템 호출을 추적하는 프로그램 인을 사용하여 설명 할 수 있습니다 . cat foo를 통해 실행 strace하면 파일 foo이 열린 것을 볼 수 있습니다 .

$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)     

위의 첫 번째 줄은 프로그램 /bin/cat이 호출되었고 그 인수가 cat이고 foo(첫 번째 인수는 항상 프로그램 자체 임) 보여줍니다. 나중에 인수 foo가 읽기 전용 모드로 열립니다. 자, 이것을 이것과 비교하십시오

$ strace ls foo 2| grep foo
execve("/bin/ls", ["ls", "foo"], [/* 44 vars */]) = 0
stat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(1, "foo\n", 4foo

여기 또한, ls자신을 데리고 foo인수로. 그러나 open호출 이 없으며 인수는 입력으로 처리되지 않습니다. 대신 ls시스템 stat라이브러리 ( stat명령 과 동일하지 않음 )를 호출 하여 파일에 대한 정보를 얻습니다 foo.

요약하면, 실행중인 명령이 입력을 읽는다면 파이프로 연결할 수 있으며 그렇지 않은 경우 파이프로 연결할 수 없습니다.


답변

  • kill 또는 rm과 함께 작동하지 않는 이유는 무엇입니까?

killrmSTDIN 필요하지 않습니다.

  • grep을 사용한 kill, rm 입력, awk 입력의 차이점은 무엇입니까?

들어 killrm, 사용자는 인수로 자신의 맞춤형 정보를 제공하고, $(cmd)의 STDOUT을 복용하는 데 도움이 cmd그것에게 정보 인수를 변환.

들어 grepawk, 사용자는 인수 및뿐만 아니라, 또한 제공 STDIN또는 명령에 의해 처리됩니다 일반 파일을. STDIN파이프 라인 |이나 수동 입력으로 전달할 수 있습니다 .

  • 규칙이 있습니까?

매뉴얼 또는 소스 코드를 읽으십시오. 필요한 것을 찾지 못하면 간단하지만 위험한 테스트를 할 수 있습니다.

이미 이해하고있는 인수를 사용하여 궁금한 명령을 입력하고 명령이 일시 중지되는지 (아무 일도 없는지) 확인하십시오. 일시 정지되면 실제로 STDIN을 기다리는 중입니다 ( 다른 시도를 시도 cat하고 echo볼 수 있음 ). 수동으로 입력 Ctrl-D하면 명령이 진행되고 (결과 또는 오류 표시) 반환됩니다. 이러한 명령에는 해당 상황에서 STDIN이 필요합니다 (제공 한 인수 포함).

동일한 명령이 다른 상황에서 STDIN이 필요하지 않을 수 있습니다 (예 : catSTDIN을 기다리지 만 기다리지 cat file.txt않음).