Tidak dapat menangkap output ke dalam variabel di Bash

15

Kesulitan dengan redis-cli. Saya ingin memeriksa apakah koneksi ke redisditolak (server down), melalui BASH.

Tes sederhana

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

Saya berharap Could not connect to Redis at 127.0.0.1:6379: Connection refuseduntuk disimpan dalam $ test, tetapi teks ini adalah output ke konsol sebagai gantinya.

Saya tidak yakin apa yang terjadi. Adakah yang punya ide?

(Ubuntu 14.04.1)

DarkNeuron
sumber
Perhatikan bahwa if [[ -z $test ]]hampir pasti akan meluas ke if [[ -z ]]saat $testmenjadi kosong, yang tampaknya akan menembus kondisi. Untuk melindungi terhadap ini, hanya menempatkan variabel dalam tanda kutip: if [[ -z "$test" ]] ; then.
CVn
Saya benar-benar berpikir bahwa versi bash yang lebih baru mengatasinya. Sepertinya tetap bekerja dalam tes saya.
DarkNeuron
Baiklah, bagus untukmu. :-) Saya cenderung menyukai jaring pengaman tambahan, jika tidak ada yang lain untuk menjaga kewarasan saya ketika melihat kode nanti ...
sebuah CVn

Jawaban:

20

Itu karena pesan kesalahan sedang dikirim ke aliran STDERR (file descriptor 2), bukan STDOUT (file deskriptor 1) yang Anda tangkap dengan substitusi perintah $().

Hanya berfokus pada mendapatkan string, baik pada STDOUT atau STDERR:

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

dalam hal ini [ -z "$test" ]pengujian akan menghasilkan false positive karena pesan kesalahan akan disimpan dalam variabel. Sebagai gantinya Anda dapat melakukan:

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

Juga saya pikir, ini harus mendapatkan apa yang Anda inginkan mengingat status keluar sepele:

if redis-cli exit &>/dev/null; then
    echo 'Succeeded!!'
else
    echo 'Failed!!'
fi
heemayl
sumber
Ah, tentu saja. Itu kesalahan! :)
DarkNeuron
Juga, itu meminta masalah (jika hanya sedikit) untuk menggunakan nama perintah bawaan (dan dapat dieksekusi) - "test" untuk nama variabel, jadi hanya menguji status keluar seperti pada solusi kedua lebih baik untuk alasan itu juga.
Joe