Impossible de capturer la sortie en variable dans Bash

15

Avoir des problèmes avec redis-cli. Je veux vérifier si la connexion à redisest refusée (serveur arrêté), via BASH.

Test simple

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

Je m'attendrais Could not connect to Redis at 127.0.0.1:6379: Connection refusedà être stocké dans $ test, mais ce texte est plutôt affiché sur la console.

Je ne suis pas sûr de ce qui se passe. Quelqu'un a des idées?

(Ubuntu 14.04.1)

DarkNeuron
la source
Notez que if [[ -z $test ]]presque certainement étendre à if [[ -z ]]quand $testest vide, ce qui semble susceptible de briser le conditionnel. Pour protéger contre cela, il suffit de mettre la variable entre guillemets: if [[ -z "$test" ]] ; then.
un CV
En fait, je pense que les nouvelles versions de bash gèrent cela. Semble fonctionner dans mes tests de toute façon.
DarkNeuron
Eh bien, c'est bon pour toi. :-) J'ai tendance à aimer le filet de sécurité supplémentaire, si rien d'autre pour préserver ma raison en regardant le code plus tard ...
un CVn

Réponses:

20

C'est parce que le message d'erreur est envoyé au flux STDERR (descripteur de fichier 2), pas à STDOUT (descripteur de fichier 1) que vous capturez avec la substitution de commande $().

Se concentrer uniquement sur l'obtention de la chaîne, soit sur STDOUT soit sur STDERR:

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

dans ce cas, le [ -z "$test" ]test entraînera des faux positifs car le message d'erreur sera stocké dans la variable. Au lieu de cela, vous pouvez faire:

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

Je pense également que cela devrait obtenir ce que vous voulez étant donné que le statut de sortie est trivial:

if redis-cli exit &>/dev/null; then
    echo 'Succeeded!!'
else
    echo 'Failed!!'
fi
heemayl
la source
Ah, bien sûr. C'est une erreur! :)
DarkNeuron
En outre, cela demande des problèmes (ne serait-ce qu'un petit peu) pour utiliser le nom d'une commande intégrée (et exécutable) - "test" pour un nom de variable, donc il suffit de tester l'état de sortie comme dans la deuxième solution pour cette raison aussi.
Joe