Nie można przechwycić danych wyjściowych do zmiennej w Bash

15

Kłopoty z redis-cli. Chcę sprawdzić, czy połączenie redisjest odrzucone (serwer nie działa), przez BASH.

Prosty test

#!/bin/bash
test=$(redis-cli exit) #exit out of the "not connected console"
if [[ -z $test ]] ; then
    echo "I'm empty :("
fi

Oczekiwałbym, Could not connect to Redis at 127.0.0.1:6379: Connection refusedże będę przechowywany w teście $, ale ten tekst jest zamiast tego wysyłany do konsoli.

Nie jestem pewien, co się dzieje. Czy ktoś ma jakieś pomysły?

(Ubuntu 14.04.1)

DarkNeuron
źródło
Zauważ, że if [[ -z $test ]]prawie na pewno rozszerzy się, if [[ -z ]]kiedy stanie $testsię pusty, co wydaje się prawdopodobnie złamać warunek. Aby zabezpieczyć się przed tym, po prostu umieścić zmienną w cudzysłowie: if [[ -z "$test" ]] ; then.
CVn
Właściwie myślę, że nowsze wersje bash sobie z tym radzą. W każdym razie wydaje się, że zadziała w moich testach.
DarkNeuron
Dobrze więc dla ciebie. :-) Zwykle podoba mi się dodatkowa siatka bezpieczeństwa, jeśli nic innego, aby zachować moje zdrowie psychiczne, gdy patrzę na kod później ...
CVn

Odpowiedzi:

20

Jest tak, ponieważ komunikat o błędzie jest wysyłany do strumienia STDERR (deskryptor pliku 2), a nie STDOUT (deskryptor pliku 1), który przechwytujesz za pomocą podstawiania poleceń $().

Skupiając się na pobieraniu ciągu, albo na STDOUT, albo na STDERR:

test="$(redis-cli exit 2>&1)"

w takim przypadku wynik [ -z "$test" ]testu będzie fałszywie dodatni, ponieważ komunikat o błędzie zostanie zapisany w zmiennej. Zamiast tego możesz:

#!/bin/bash
test="$(redis-cli exit 2>/dev/null)"
if [[ -z $test ]] ; then
    echo "I'm empty :("
fi

Myślę też, że powinno to uzyskać to, czego oczekujesz, ponieważ status wyjścia jest trywialny:

if redis-cli exit &>/dev/null; then
    echo 'Succeeded!!'
else
    echo 'Failed!!'
fi
heemayl
źródło
Ach, oczywiście. To błąd! :)
DarkNeuron
Prosi także o kłopoty (choćby trochę) z użyciem nazwy wbudowanej komendy (i pliku wykonywalnego) - „test” dla nazwy zmiennej, więc po prostu testowanie statusu wyjścia, jak w drugim rozwiązaniu, jest lepsze dla także z tego powodu.
Joe,