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


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.