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


19

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

예를 들어 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 의 차이점은 무엇입니까 ?
  • 규칙이 있습니까?

1
이것은 대답이 아니지만 pgrep, pkillkillall명령을 살펴볼 수 있습니다 .
terdon

2
@terdon : 파이프 라인 문제를 보여주기 위해 위의 시나리오를 사용합니다. 나는 pgrep나머지가 이것을 완벽하게 달성 할 수 있음을 이해합니다 :)
sylye

답변:


17

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

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

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

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

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

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

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


1
명령이 인수 만 취하고 STDIN 은 취하지 않는 것을 어떻게 알 수 있습니까? 매뉴얼 페이지를 추측하거나 읽는 것보다 체계적이거나 프로그래밍 방식이 있습니까? 맨 페이지를 읽음으로써 STDIN도 맨 페이지가 존재하는 방식의 인수의 일부이므로 명령이 STDIN을 취할 수 있는지 여부에 대한 확실한 단서를 얻을 수 없었습니다. 예를 들어, gzipSYNOPSIS에서는 FILENAME을 입력해야한다고 말하지 않았습니다. 나는 그것을 결정하는보다 체계적인 방법을 찾고 있습니다.
sylye

일부 명령에 대해 "stdin"(또는 "stdout")을 의미하는 "-"인수도 있습니다.
Emmanuel

xargs"파이프-명령 행 인수"를 정확하게 허용 하지 않습니까?
T. Verron

@ T.Verron 네,이 작업입니다 xargs. 필요한 경우 두 번 이상 명령을 호출하고 (명령 줄 크기가 제한됨) 다른 많은 옵션이 있습니다.
jofel

2
설명 텍스트는 프로그램 사용 방법을 설명합니다. 예를 들어, gzip은 다음과 같이 말합니다. "gzip 프로그램은 Lempel-Ziv 코딩 (LZ77)을 사용하여 파일을 압축 및 압축 해제합니다. 파일을 지정하지 않으면 gzip은 표준 입력에서 압축되거나 표준 출력으로 압축 해제됩니다." 매뉴얼 페이지에 표준 입력이 없으면 사용하지 않습니다.
Alan Shutko

16

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

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

필터 양태

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

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

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

의미 양태

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

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

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

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


5

"규칙"은 없습니다. 일부 프로그램은 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.

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


0
  • 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않음).

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