성공시에만 쉘 명령의 출력을 숨기시겠습니까?


12

쉘 명령의 출력을 숨기려면 일반적으로 stderr 및 stdout을 경로 재지 정해야합니다. 기본적으로 출력을 숨기지 만 오류시 누적 된 모든 출력을 덤프하는 내장 기능 또는 명령이 있습니까? 이것을 원격 ssh명령 의 래퍼로 실행하고 싶습니다 . 이제 리디렉션을 사용하고 있지만 실패한 원인에 대한 단서가 없으며 너무 자세합니다.

편집 : 결국 @Belmin의 답변을 기반으로 스크립트에서 이전 명령을 모두 누적하고 현재 프로세스 식별자를 사용하고 로그를 자동으로 제거하고 실패 빨간색 오류를 추가하기 위해 약간의 조정을 바탕으로 다음 템플릿을 만들었습니다. 무언가 잘못되었을 때 메시지. 이 템플리트에서 초기 silent랩퍼는 성공한 후 디렉토리가 이미 존재하므로 세 번째 명령이 실패합니다.

#!/bin/sh

set -e

SILENT_LOG=/tmp/silent_log_$$.txt
trap "/bin/rm -f $SILENT_LOG" EXIT

function report_and_exit {
    cat "${SILENT_LOG}";
    echo "\033[91mError running command.\033[39m"
    exit 1;
}

function silent {
    $* 2>>"${SILENT_LOG}" >> "${SILENT_LOG}" || report_and_exit;
}

silent mkdir -v pepe
silent mkdir -v pepe2
silent mkdir -v pepe
silent mkdir -v pepe2

2
stdout 만 리디렉션하면 stderr이 계속 나타납니다. 이것으로 충분합니까, 아니면 오류가있는 경우 stdout을보고 싶습니까?
Kromey

둘 다보고 싶지만 문제가 발생했을 경우에만, 그렇지 않으면 아무것도보고 싶지 않습니다.
Grzegorz Adam Hankiewicz

2
내가하는 일은 stdout & stderr을 로그 파일에 인쇄하여 화면을 어지럽히 지 않는 것입니다. 또한 stderr을 화면에 인쇄하므로 오류 있으면 볼 수 있습니다. 세부 정보가 필요한 경우 프로그램 출력과 컨텍스트에서 프로그램 오류가 포함 된 로그 파일을 확인할 수 있습니다. 이런 식으로, 나는 '무언가 잘못되었을 때만 둘 다 볼 수 있습니다'. 도움이 되나요? 참조 stackoverflow.com/questions/2871233/...
스테판 Lasiewski

1
두 개의 별도 리디렉션으로 stderr 및 stdout을 동일한 파일로 리디렉션하는 것이 안전합니까? 나는 우리가 항상 2>&1다음과 같은 것을 사용해야한다고 생각했다 .$* >>"${SILENT_LOG}" 2>&1" || report_and_exit
psmith

답변:


3

다음 과 같이 bash 함수를 설정했습니다 .

function suppress { /bin/rm --force /tmp/suppress.out 2> /dev/null; ${1+"$@"} > /tmp/suppress.out 2>&1 || cat /tmp/suppress.out; /bin/rm /tmp/suppress.out; }

그런 다음 명령을 실행할 수 있습니다.

suppress foo -a bar

시스템에서 루트가 아닌 액세스 권한을 가진 공격자는 rm과 명령 호출간에 심볼릭 링크를 만들려고 시도 할 수 있습니다.이 링크는 /etc/passswd다른 중요한 파일을 가리키고 내용을 덮어 씁니다.
Mitar

1
BTW, 위의 리디렉션 순서는 다음과 같습니다. $* > /tmp/surpress.out 2>&1이것은 실제로 stderr을 캡처합니다.
Mitar

2
$*임의의 입력을 처리하는 것이 가장 좋습니다. 특히 공백이나 플래그가 포함 된 경우. 대부분의 휴대용입니다 ${1+"$@"}에 따른 stackoverflow.com/questions/743454/...
balrok

두 의견에 따라 수정되었습니다. 감사합니다-좋은 정보입니다.
Belmin Fernandez


7

이 목적을 위해 스크립트를 작성하는 것이 쉬워야합니다.

이 완전히 테스트되지 않은 스크립트와 같은 것.

OUTPUT=`tempfile`
program_we_want_to_capture &2>1 > $OUTPUT
[ $? -ne 0 ]; then
    cat $OUTPUT
    exit 1
fi
rm $OUTPUT

반면에 명령의 경우 스크립트의 일부로 실행하면 일반적으로 단순히 모든 출력을 인쇄하는 것보다 더 나은 것을 원합니다. 나는 종종 내가 알 수없는 것으로 제한합니다. 다음은 제가 10 년 전에 읽은 내용에서 수정 한 스크립트입니다.

#!/bin/bash

the_command 2>&1 | awk '
BEGIN \
{
  # Initialize our error-detection flag.
  ErrorDetected = 0
}
# Following are regex that will simply skip all lines
# which are good and we never want to see
/ Added UserList source/ || \
/ Added User/ || \
/ init domainlist / || \
/ init iplist / || \
/ init urllist / || \
/ loading dbfile / || \
/^$/ {next} # Uninteresting message.  Skip it.

# Following are lines that we good and we always want to see
/ INFO: ready for requests / \
{
  print "  " $0 # Expected message we want to see.
  next
}

# any remaining lines are unexpected, and probably error messages.  These will be printed out and highlighted.
{
  print "->" $0 # Unexpected message.  Print it
  ErrorDetected=1
}

END \
{
  if (ErrorDetected == 1) {
    print "Unexpected messages (\"->\") detected in execution."
    exit 2
  }
}
'
exit $?

5

나는 이것을하는 깨끗한 방법이 없다고 생각합니다. 내가 생각할 수있는 유일한 것은

  • 명령의 출력을 캡처하십시오.
  • 명령의 반환 값을 확인하고 실패한 경우
    • 캡처 된 출력을 표시합니다.

이것을 구현하는 것은 흥미로운 프로젝트이지만 아마도 Q & A를 넘어서는 것입니다.


기능으로 수행 할 수 있어야합니다. 흠, 한번 해보자.
벨민 페르난데스

1

다음과 같이 부족해 tehcommand &>/tmp/$$ || cat /tmp/$$

사용성 / 타이핑 정도 / 필요한 정도에 따라 다릅니다. (예 : 파이프로 사용하거나 인수로 명령 전달)

@zoredache 짧은 스크립트는 기본적으로 이것에 대한 프로토 래퍼입니다. 더 많은 견고성, 동시성 처리 등


1

그렇게 해보십시오 :

out=`command args...` || echo $out

2
나는 다음과 같이 out="$(command args...)" || echo "$out"
썼다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.