한 프로세스에서 다른 프로세스로 출력을 파이프하지만 첫 번째 출력이있는 경우에만 실행하는 방법은 무엇입니까?


23

에서 출력이있는 경우 전자 메일로만이 명령을 다시 작성하려면 mailq | grep어떻게 해야 합니까?

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email

한 줄로도 가능합니까?

이메일을 보내는 것보다 일반적인 경우 가 아닌 경우 파이프가 비어 있는지 확인하고 데이터에서 명령 실행을 참조 하십시오 .


답변:


19

&&grep이 다음과 일치하는 종료 상태를 리턴 한 경우 연산자를 사용 하여 mail 명령 만 실행할 수 있도록이 조작에 임시 파일을 사용해야한다고 생각합니다 .

TMPFILE=`mktemp /tmp/mailqgrep.XXXXXX`; mailq | egrep 'rejected|refused' -A5 -B5 > "$TMPFILE" && mail -s 'dd' email@email < "$TMPFILE"; rm "$TMPFILE"

임시 파일이 어딘가에 붙어 있고 정적 이름을 사용할 수 없다면 특별한 이름 지정 및 삭제 항목을 건너 뛸 수 있습니다.

 mailq | egrep 'rejected|refused' -A5 -B5 > /tmp/mailqgrep && mail -s 'dd' email@email < /tmp/mailqgrep

편집 : glenn의 대답을 본 후에이 부분을 더 연주하고 $()구문을 사용하여 변수를 할당 하면 명령의 종료 코드가 반환되므로 문자열 길이에 사용한 테스트를 건너 뛰고 대신 사용할 수 있습니다. 여기에 하나의 명령이 있습니다.

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) && mail -s 'dd' email@email <<< "$data"

편집 2 : Simon의 답변을 본 후 mail프로그램을 확인했습니다 . 기본적으로 설명 된 방식으로 작동하지 않지만 이에 대한 옵션이 있습니다. 매뉴얼 페이지에서 :

-E발신 메시지의 첫 번째 또는 유일한 메시지 부분에 텍스트가 포함되어 있지 않으면 메시지를 보내지 말고 자동으로 삭제하여 프로그램 시작시 skipemptybody 변수를 효과적으로 설정하십시오. cron (8)으로 시작된 스크립트에서 메시지를 보내는 데 유용합니다.

가능하게하기 :

mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -E -s 'dd' email@email

1
협업의 힘 !!
glenn jackman 2016 년

3
최고의 솔루션을 맨 위로 옮기면이 답변을 더 잘 만들 수 있다고 제안합니다 .
Mark Booth

@Wildcard 입력 매개 변수 mktemp가 인용이 필요한 것을 반환하지 않기 때문에 편집이 불필요 합니다.
Caleb

2
알아. 당신은 따옴표 때때로 필요 하다는 것을 이해하기 위해 귀찮게하는 몇 안되는 사람 중 하나입니다 (의도적으로 생략합니다). 그러나을 명시 적으로 호출하지 않는 한 기본값 따옴표로 묶어야합니다 glob(split(var)). 여기에서 단어 분할 또는 파일 글로브 확장이 필요하지 않으므로 요청하지 마십시오. 또한 이 사이트 에서 올바른 방법 을 보여 주어야합니다 .
와일드 카드

@ 와일드 카드 페어. 나는 일반적으로 실행 zsh실제로하고 있지 내가 그들을 요청하지 않는 한이 같은 경우에 글 로빙 또는 단어 분할을 받고 있지만, 여기가 아니라 답변을 위해 원칙 밖으로 인용 대상 환경을 알고 괜찮습니다.
Caleb

11

유틸리티 프로그램 ifne 은이 목적을 위해 명시 적으로 존재합니다. 표준 입력이 비어 있지 않은 경우 명령을 실행합니다.

mailq | egrep 'rejected|refused' -A 5 -B 5 | ifne mail -s 'dd' email@email

ifne 명령은 moreutils 패키지의 일부이며 "유닉스가 어렸을 때 아무도 오래 전에 생각하지 않은 유닉스 도구 모음"으로 표시됩니다.


8

출력을 변수에 저장 한 다음 문자열 길이가 0이 아닌 경우 mail 명령을 호출 할 수 있습니다.

data=$(mailq | egrep 'rejected|refused' -A 5 -B 5)
[[ -n "$data" ]] && mail -s 'dd' email@email <<< "$data"

한 줄의 경우 두 명령을 세미콜론으로 연결하십시오.


1
임시 파일 대신 변수를 사용하기위한 소품. 이것은 변수 할당을 한 명령에서 종료 코드가 어디에서 나오는지에 대해 생각하게하고 분명히 전달됩니다! 내 업데이트 된 답변을 참조하십시오 .
Caleb

7

옵션 mail과 함께 사용하십시오 -E. 내 Mac에서 MAIL (1)은 -E깃발이 비어있는 이메일을 보내지 않을 것이라고 말합니다 .

-E 본문이 비어있는 메시지를 보내지 마십시오. 이것은 cron (8) 스크립트에서 파이핑 오류에 유용합니다.

내 Mac에서 다음 테스트를 실행했습니다. 파일 file_does_exist은 존재하지만 파일 은 존재 file_does__not_exist하지 않습니다.

이것은 나에게 이메일을 보냅니다 :

$ ls file_does_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org

그렇지 않습니다. 명령 ls file_does_not_exist | egrep ...은 출력을 생성하지 않습니다.

$ ls file_does_not_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org
ls: file_does_not_exist: No such file or directory

갈렙이 당신을 이겼습니다.
Gilles 'SO- 악마 중지'

1
그는 단지 4.75 시간 만 나를 이겼다 :). 그의 긴 대답 에서이 세부 사항을 놓쳤습니다.
Stefan Lasiewski

5

이 특별한 경우, 옵션을 지원하는 경우mail-E 사용하십시오. 일반적인 경우 한 문자를 읽으려고 시도 할 수 있습니다. 있는 경우 사후 처리 명령을 시작하고 파일의 나머지 부분에서 해당 문자를 제공하십시오.

pipe_if_not_empty () {
  a=$(dd bs=1 count=1 2>/dev/null; echo .)  # read at most one character
  if [ "$a" != "." ]; then                  # if there were two characters,
    { printf %s "${a%.}";                   # then output the first character
      cat; } |                              # and the rest of the input   
    "$@"                                    # into the specified program
  fi
}

mailq | egrep 'rejected|refused' -A 5 -B 5 |
pipe_if_not_empty mail -s 'dd' email@email

의 유용한 사용법에 유의하십시오 cat. 추가 echo .하면 입력의 첫 번째 문자가 줄 바꿈 인 경우에도이 함수가 작동합니다 ( $(…)구문 이 줄 바꿈을 제거함을 기억하십시오 ).

대부분의 쉘 (내가 아는 한 zsh 이외의 것)에서 파일이 null 문자로 시작하면이 코드는 비어 있다고 믿습니다. 독자를위한 연습으로 남겨진 고정. (힌트 : od첫 번째 서브 쉘에서 사용 printf하고 첫 번째 바이트를 인쇄합니다.) (해결 방법 : 파이프가 비어 있는지 확인하는 방법 ) 파일이 현재 문자가 아닌 바이트로 시작하면 같은 문제가 발생할 수 있습니다. 장소; 로이 코드를 실행하면 쉽게 해결할 수 LC_ALL=C있습니다.


어리석은 일이지만 다른 시나리오에서는 유용 할 수있는 +1 :) 호기심 때문에 빈 문자열을 테스트하는 대신 점을 주입하고 테스트해야하는 이유 입력이 점으로 시작하면 문제가되지 않습니까? read이것을 사용 하면 이것을 단순화 하는 데 도움이 될 수 있습니까?
Caleb

@Caleb : 네, 특정 상황이 아니라 제목의 질문에 답하고 있다고 언급 했어야합니다. 점에 대한 설명은 내 편집을 참조하십시오. read휴대용 sh를 사용 하여 빈 첫 줄을 빈 파일과 구별 할 수 있다고 생각하지 않습니다 (bash, ksh 또는 zsh에서 가능할 수 있음).
Gilles 'SO- 악마 중지'


1

최근 ifne에는 moreutils패키지의 일부인 명령 이름에 대해 배웠습니다 . 이 특정 문제를 해결하기 위해 사용할 수있는 곳.

ifne- 표준 입력이 비어 있지 않은 경우 명령 실행

맨 페이지의 예

EXAMPLE
       find . -name core | ifne mail -s "Core files found" root

0

부품의 test -s /dev/stdin출력이 있는지 확인하는 데 사용하여 명령을 다시 작성할 수 있습니다 mailq | grep.

- mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email
+ mailq | egrep 'rejected|refused' -A 5 -B 5 | (test -s /dev/stdin && cat) | mail -s 'dd' email@email
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.