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

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

파이프를 사용해야 하는 경우와 파이프를 사용하지 말아야 하는 경우를 알고 싶습니다.

예를 들어 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입력 rm과 입력 grep의 차이점은 무엇입니까 awk?
  • 어떤 규칙이 있나요?

답변1

이것은 Unix/Linux 철학의 일부를 다루는 흥미로운 질문입니다.

grep그렇다면 , , 같은 프로그램과 , , 같은 프로그램 sed의 차이점 은 무엇인가요 ? 나는 양쪽을 본다.sortkillrmls

이것필터측면

  • 첫 번째 유형의 프로그램이라고도합니다.필터. 파일이나 STDIN에서 입력을 받아 수정하고 주로 STDOUT과 같은 일부 출력을 생성합니다. 이는 다른 프로그램을 소스 및 대상으로 사용하는 파이프라인에서 사용하기 위한 것입니다.

  • 두 번째 유형의 프로그램은 입력에 따라 작동하지만 제공되는 출력은 일반적으로 입력과 독립적입니다. kill정상적으로 작동할 때는 출력도 없고 아무것도 없습니다 rm. 성공을 나타내는 반환 값만 있으면 됩니다. 일반적으로 STDIN에서 입력을 받지 않지만 대부분 STDOUT에 출력을 제공합니다.

ls필터 측면은 . 물론 입력이 있을 수 있지만(꼭 그럴 필요는 없음), 출력은 해당 입력과 밀접하게 관련되어 있지만 필터 역할을 할 수는 없습니다. 그러나 이러한 프로그램의 경우 또 다른 측면이 유효합니다.

이것의미론측면

  • 필터의 경우 입력은 다음과 같습니다.의미상 의미 없음. 그들은 단지 데이터를 읽고, 데이터를 수정하고, 데이터를 출력합니다. 이것이 값 목록인지, 일부 파일 이름인지, HTML 소스 코드인지는 중요하지 않습니다. 이 데이터의 의미는 코드에 의해서만 제공됩니다.필터에 정규식 grep, 규칙 awk또는 Perl 프로그램을 제공하십시오.

  • kill또는 와 같은 다른 프로그램의 경우 ls입력에는중요성,ㅏ표현하다. kill프로세스 ID, ls파일 이름 또는 경로 이름이 필요합니다. 임의의 데이터를 처리할 수 없으며 의도된 것도 아닙니다. 이들 중 다수는 입력이나 매개변수도 필요하지 않습니다 ps. 예를 들어 일반적으로 STDIN에서 읽지 않습니다.

이 두 가지 측면을 결합할 수 있습니다. 필터는 입력이 프로그램에 의미론적 의미를 갖지 않는 프로그램입니다.

분명히 이 철학에 대해 어디선가 읽었을 것입니다. 하지만 지금은 어떤 출처도 기억나지 않습니다. 죄송합니다. 출처가 있으신 분은 자유롭게 수정해주시기 바랍니다.

답변2

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

  • 프로세스의 STDIN에 데이터 제공
  • 명령줄 매개변수 지정

kill명령줄 매개변수만 사용하세요. STDIN에서는 읽지 않습니다. 프로그램은 STDIN에서 데이터를 grep읽고 awk(명령줄 인수로 파일 이름이 지정되지 않은 경우) 명령줄 인수(모드, 명령문, 플래그 등)에 따라 데이터를 처리하는 것을 좋아합니다.

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

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

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

완전성을 위해: STDOUT에 명령줄 인수를 쓰려면 echo.

답변3

그러한 "규칙"은 없습니다. 일부 프로그램은 STDIN의 입력을 받아들이고 일부 프로그램은 그렇지 않습니다. 프로그램이 STDIN에서 입력을 얻을 수 있으면 파이프로 연결할 수 있지만 그렇지 않으면 그럴 수 없습니다.

일반적으로 프로그램이 수행하는 작업을 고려하여 프로그램이 입력을 허용하는지 여부를 알 수 있습니다. 프로그램의 임무가 어떤 방식으로든 조작하는 것이라면콘텐츠grep일반적으로 STDIN에서 입력을 받는 파일 (예: 등)입니다. 작업이 파일 자체(예: ) 또는 프로세스(예: )에서 작동하거나 무언가에 대한 정보(예: )를 반환하는 것이라면 그렇지 않습니다.sedawkmvrmcpkilllsoftopfindps

이에 대해 생각하는 또 다른 방법은 매개변수와 입력의 차이입니다. 예를 들어:

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 foovia를 실행하면 파일이 열려 있는 strace것을 볼 수 있습니다 .foo

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

위의 첫 번째 줄은 프로그램이 인수 와 /bin/cat함께 호출된다는 것을 보여줍니다 (첫 번째 인수는 항상 프로그램 자체입니다). 나중에 매개변수는 읽기 전용 모드로 열립니다. 이제 다음과 결합하세요.catfoofoo

$ 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

여기서는 lsself와 foo인수를 사용합니다. 그러나 호출이 없으며 open매개변수가 입력으로 간주되지 않습니다. 대신, 파일에 대한 정보를 얻기 위해 ls시스템의 stat라이브러리(명령과 별개 )가 호출됩니다 .statfoo

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

답변4

  • 왜 kill이나 rm과 함께 작동하지 않습니까?

kill그리고 rmSTDIN이 필요하지 않습니다.

  • Kill 및 rm 입력과 grep 및 awk 입력의 차이점은 무엇입니까?

kill및 의 경우 rm사용자는 사용자 정의 정보를 매개변수로 제공하고 $(cmd)도움말은 STDOUT을 가져와서 cmdinfo 매개변수로 변환합니다.

grep및 의 경우 awk사용자는 인수와 더불어 STDIN명령으로 처리될 일반 파일을 제공합니다. STDIN이는 파이프로 연결 |하거나 수동으로 입력할 수 있습니다.

  • 어떤 규칙이 있나요?

매뉴얼이나 소스코드를 읽어보세요. 필요한 것을 찾지 못한 경우 간단하지만 잠재적으로 위험한 테스트를 수행할 수 있습니다.

관심 있는 명령과 이미 알고 있는 매개변수를 입력하고 명령이 일시 중지되는지(아무 일도 일어나지 않음) 확인하세요. 일시 중지되면 실제로는 STDIN을 기다리고 있는 것입니다( 차이점을 cat확인해 볼 수 있습니다). echo수동으로 입력 Ctrl-D하면 명령이 계속 실행되고(결과 또는 오류 표시) 반환됩니다. 이 경우 해당 명령에는 STDIN(및 사용자가 제공하는 인수)이 필요합니다.

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

관련 정보