Pytanie W bashu znajduje się odpowiednik "error msg" matrycy


W perlu możesz wyjść z komunikatem o błędzie z die "some msg". Czy istnieje odpowiednik pojedynczego polecenia w bash? W tej chwili uzyskuję to za pomocą poleceń: echo "some msg" && exit 1


52
2017-10-23 20:02


pochodzenie




Odpowiedzi:


Możesz łatwo rzucić własną:

die() { echo "$*" 1>&2 ; exit 1; }
...
die "Kaboom"

51
2017-10-23 20:43



+1; ale zauważ, że kostka bez argumentów emituje niechciany znak nowej linii. Lubię "{test -n" $ @ "&& echo" $ @ "; wyjście 1; }> I 2 " - William Pursell
@WilliamPursell: Możesz użyć printf %s "${@+$@$'\n'}" - Innymi słowy, wypisz argumenty, po których następuje znak nowej linii, jeśli istnieją. - l0b0
Patrząc wstecz na tę odpowiedź 6 lat później, zdaję sobie z tego sprawę "$*" prawdopodobnie ma więcej sensu niż "$@". Zachowanie będzie w większości przypadków identyczne, ale różni się dla die -n Oops (nie, że chciałbyś to zrobić). - Keith Thompson


Oto, czego używam. Jest zbyt mały, aby umieścić go w bibliotece, więc musiałem wpisywać go setki razy ...

warn () {
    echo "$0:" "$@" >&2
}
die () {
    rc=$1
    shift
    warn "$@"
    exit $rc
}

Stosowanie: die 127 "Syntax error"


22
2017-10-23 20:46





Jest to bardzo bliska funkcja "umierania" perla (ale z nazwą funkcji):

function die
{
    local message=$1
    [ -z "$message" ] && message="Died"
    echo "$message at ${BASH_SOURCE[1]}:${FUNCNAME[1]} line ${BASH_LINENO[0]}." >&2
    exit 1
}

I bash sposób umierania, jeśli wbudowana funkcja nie działa (z nazwą funkcji)

function die
{
    local message=$1
    [ -z "$message" ] && message="Died"
    echo "${BASH_SOURCE[1]}: line ${BASH_LINENO[0]}: ${FUNCNAME[1]}: $message." >&2
    exit 1
}

Tak więc Bash przechowuje wszystkie potrzebne informacje w kilku zmiennych środowiskowych:

  • LINENO - bieżący numer linii wykonanej
  • FUNCNAME - zestaw wywołań funkcji, pierwszy element (indeks 0) jest funkcją bieżącą, drugi (indeks 1) jest funkcją, która nazywa bieżącą funkcję
  • BASH_LINENO - wywołanie stosu numerów linii, gdzie wywołano odpowiednią nazwę FUNCNAME
  • BASH_SOURCE - tablica pliku źródłowego, gdzie przechowywana jest odpowiednia nazwa FUNCNAME

10
2018-01-17 16:51



Możesz całkowicie pominąć zmienną lokalną ${1-Died} - dzięki temu możesz nawet przekazać pusty ciąg i będzie działać tak, jak byś tego oczekiwał. - tripleee


Tak, to prawie jak to robisz.

Możesz użyć średnika lub nowego wiersza zamiast &&, ponieważ chcesz wyjść z tego, czy echo się powiedzie (choć nie jestem pewien, co mogłoby spowodować niepowodzenie).

Programowanie w powłoce oznacza użycie mnóstwa małych poleceń (trochę wbudowanych poleceń, kilka małych programów), które dobrze wykonują jedną rzecz i łączą je z przekierowaniem pliku, logiką kodu wyjścia i innym klejem.

Może wydawać się dziwne, jeśli jesteś przyzwyczajony do języków, w których wszystko odbywa się za pomocą funkcji lub metod, ale przywykniesz do tego.


3
2017-10-23 20:14



dzięki, bonkydog. - PJx
Teraz odkrywam kolejny nieprzyjemny efekt. Podczas wykonywania polecenia echo interpreter nie czeka na zakończenie, ale jednocześnie wykonuje poniższy kod! Oto co mam: CMD1 || (echo 'ERROR MSG'; exit 1); CMD2; CMD3. Teraz, jeśli CMD1 zawiedzie, oczekuję, że nastąpi echo i wyjście, a skrypt zakończy działanie. Ale teraz, gdy CMD1 zawiedzie, CMD2 i CMD3 są faktycznie wykonywane przed echo. Jest to zgodne z protokołem błędów. Dziwaczne czy nie? - PJx
właściwie, myślę, że nawiasy () mogą być winowajcą. Wystarczy przeczytać gdzieś, że mogą wykonać kod wewnątrz podpowłoki, co oczywiście nie przyniesie pożądanego efektu. Właśnie zmieniłem kod na blok if-fi i działało zgodnie z oczekiwaniami. Tylko dla mojej ciekawości, mogę połączyć ten kod w jeden liniowiec? - PJx
Posługiwać się {} zamiast ()aby uniknąć problemu z podpowłoką. Poza tym dobrym pomysłem jest wysyłanie błędów na stderr zamiast na standardowe wyjście: CMD1 || { echo 'ERROR MSG' >&2; exit 1; }; CMD2; CMD3 - Gordon Davisson
Dzięki Gordon, bardzo pomocny. - PJx


# echo pass params and print them to a log file
wlog(){
    # check terminal if exists echo 
    test -t 1 && echo "`date +%Y.%m.%d-%H:%M:%S` [$$] $*"
    # check LogFile and 
    test -z $LogFile || {
      echo "`date +%Y.%m.%d-%H:%M:%S` [$$] $*" >> $LogFile
    } #eof test
 } 
# eof function wlog 


# exit with passed status and message
Exit(){
    ExitStatus=0
    case $1 in
      [0-9]) ExitStatus="$1"; shift 1;;
  esac
    Msg="$*"
    test "$ExitStatus" = "0" || Msg=" ERROR: $Msg : $@"
    wlog " $Msg"
    exit $ExitStatus
}
#eof function Exit

0
2018-05-11 20:10