$를 사용하는 가장 좋은 방법? bash에서?


10

$에 대한답변을 읽을 때 ? 또 다른 질문이 떠 오릅니다.

$를 사용하는 방법에 대한 모범 사례가 있습니까? bash에서?


예를 들어 봅시다 :

우리는 선형 스크립트를 가지고 있으며 모든 명령이 정상적으로 실행되었음을 알고 싶습니다. 오류 코드를 확인하고 그렇지 않은 경우 작은 함수 ( "did_it_work"라고 함)를 호출해도 괜찮다고 생각하십니까?

#!/bin/bash 

function did_it_work {
    code=$1
    if [ "$code" -ne "0" ]
    then
        echo "Error failure: code $code "
        exit 1
    fi
}

dir=some/path

mkdir -p $dir
did_it_work $? 

cd $dir
did_it_work $? 

run_some_command
did_it_work $? 

물론이 접근법은 문제가 있으면 수동으로 문제를 해결하고 스크립트를 다시 실행해야 함을 의미합니다.

이것이 좋은 생각이라고 생각합니까, 아니면 다른 모범 사례가 있습니까?

/감사

답변:


15

한 가지 일반적인 방법은 다음과 같습니다.

die() {
    IFS=' ' # make sure "$*" is joined with spaces

    # output the arguments if any on stderr:
    [ "$#" -eq 0 ] || printf '%s\n' "$*" 1>&2
    exit 1
}

다음과 같이 사용하십시오.

mkdir -p some/path || die "mkdir failed with status $?"

또는 종료 상태를 포함 시키려면 다음과 같이 변경할 수 있습니다.

die() {
    last_exit_status=$?
    IFS=' '
    printf '%s\n' "FATAL ERROR: $* (status $last_exit_status)" 1>&2
    exit 1
}

그리고 그것을 사용하는 것이 조금 더 쉽습니다.

mkdir -p some/path || die "mkdir failed"

실패하면 mkdir이미 오류 메시지를 발행했을 가능성이 높으므로 두 번째 메시지는 중복으로 표시 될 수 있습니다.

mkdir -p some/path || exit   # with the same (failing) exit status as mkdir's
mkdir -p some/path || exit 1 # with exit status 1 always

(또는 die인수없이 위 의 첫 번째 변형을 사용하십시오 )

command1 || command2이전에 보지 못한 command1경우 실행 되고 command1실패하면 실행됩니다 command2.

따라서 "디렉토리 또는 다이 만들기"처럼 읽을 수 있습니다.

귀하의 예는 다음과 같습니다.

mkdir -p some/path || die "mkdir failed"
cd some/path || die "cd failed"
some_command || die "some_command failed"

또는 dies메인 코드가 더 명확하도록 오른쪽 에서 더 정렬 할 수 있습니다 .

mkdir -p some/path         || die "mkdir failed"
cd some/path               || die "cd failed"
some_command               || die "some_command failed"

또는 명령 행이 긴 경우 다음 행에서 :

mkdir -p some/path ||
  die "mkdir failed"

cd some/path ||
  die "cd failed"

some_command ||
  die "some_command failed"

또한 이름을 some/path여러 번 사용하려는 경우 이름 을 계속 입력하지 않아도되므로 변수에 저장하여 필요할 때 쉽게 변경할 수 있습니다. 그리고 변수 인수를 명령에 전달할 때는 --옵션 구분 기호 를 사용 하여 인수로 시작하는 인수가 옵션 으로 사용 되지 않도록하십시오 -.

dir=some/path
mkdir -p -- "$dir"         || die "Cannot make $dir"
cd -P -- "$dir"            || die "Cannot cd to $dir"
some_command               || die "Cannot run some_command"

9

다음과 같이 코드를 다시 작성할 수 있습니다.

#!/bin/bash
function try {
    "$@"
    code=$?
    if [ $code -ne 0 ]
    then
        echo "$1 did not work: exit status $code"
        exit 1
    fi
}

try mkdir -p some/path
try cd some/path
try run_some_command

실제로 오류 코드를 기록 할 필요는 없지만 명령의 성공 여부는 try()다음과 같이 더 짧게 할 수 있습니다 .

function try {
    if ! "$@"
    then
        echo "$1 did not work"
        exit 1
    fi
}

이 형식으로 코드를 사용할 수도 있습니다. <pre> 기능 시험 {
BillThor

이 기능 인라인을 사용하고 진정한 측면에서 반환 할 수없는 경우 당신은 대체 할 수 return $?:내장.
BillThor

8

실제로 exit오류가 발생하여 Bash를 사용하는 경우을 고려해야 set -e합니다. 보낸 사람 help set:

-e 명령이 0이 아닌 상태로 종료되면 즉시 종료합니다.

이것은 물론 did_it_work () 함수의 유연성을 제공하지는 않지만 새 함수에 많은 호출을 추가하지 않고 bash 스크립트가 오류를 멈추게하는 쉬운 방법입니다.


set -e유용합니다. 정상적인 상황에서 0이 아닌 값을 반환하는 명령이 있습니다 (예 :) diff. 0이 아닌 리턴을 기대하는 스크립트에서 set -e를 사용하면 command || true.
Shawn J. Goff

2
또한를 사용하더라도 set -e"예외 처리기"를 설정하여 모든 오류를 포착 할 수 있습니다 trap did_it_work EXIT.
Gilles 'SO- 악마 그만해

1
이것은 bash 특정 기능이 아닌 POSIX의 일부입니다. 그것을 사용하지만, 일부 함정의 인식 mywiki.wooledge.org/BashFAQ/105
kmkaplan

@ ShawnJ.Goff 선호합니다 command && true. 이와 같이 반환 값은 변경 되지 않습니다 .
kmkaplan

@kmkaplan 마지막 의견은 이해가되지 않습니다. 종료 코드가 0이 아닌 경우 스크립트 종료 command || true를 막는 것이 목적입니다 . 우리가해야하기 때문에 종료 코드가 변경됩니다. `command가 성공하면 (제로 종료 코드를 반환) 유일한 동작은 실행됩니다 (제로 종료 코드를 반환)-완전한 no-op입니다. set -ecommandcommand && truetrue
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.