web-dev-qa-db-fra.com

Comment faire "sinon condition vraie"?

J'aimerais que la commande echo soit exécutée lorsque cat /etc/passwd | grep "sysa" n'est pas vrai.

Qu'est-ce que je fais mal?

if ! [ $(cat /etc/passwd | grep "sysa") ]; then
        echo "ERROR - The user sysa could not be looked up"
        exit 2
fi
272

essayer

if ! grep -q sysa /etc/passwd ; then

grep renvoie true s'il trouve la cible de la recherche et false s'il ne le trouve pas.

Donc, PAS false == true.

if l'évaluation dans les shells est conçue pour être très flexible et ne nécessite souvent pas de chaînes de commandes (comme vous l'avez écrit).

En outre, si vous examinez votre code tel quel, votre utilisation de la forme $( ... ) de substitution de cmd doit être recommandée, mais réfléchissez à ce qui sort du processus. Essayez echo $(cat /etc/passwd | grep "sysa") pour voir ce que je veux dire. Vous pouvez aller plus loin en utilisant l'option -c (count) pour grep puis faire if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then qui fonctionne mais qui est plutôt old school.

MAIS, vous pouvez utiliser les dernières fonctionnalités de Shell (évaluation arithmétique) comme

if ! (( $(grep -c "sysa" /etc/passwd) == 0 )) ; then ...`

ce qui vous donne également l'avantage d'utiliser les opérateurs de comparaison basés sur c-lang, ==,<,>,>=,<=,% et peut-être quelques autres.

Dans ce cas, selon un commentaire d’Orwellophile, l’évaluation arithmétique peut être encore réduite, comme

if ! (( $(grep -c "sysa" /etc/passwd) )) ; then ....

OR

if (( ! $(grep -c "sysa" /etc/passwd) )) ; then ....

Enfin, il existe un award appelé Useless Use of Cat (UUOC). :-) Certaines personnes vont sauter et pleurer gothca! Je dirais simplement que grep peut prendre un nom de fichier sur sa cmd-line, alors pourquoi invoquer des processus supplémentaires et des constructions de canaux alors que ce n'est pas obligatoire? ;-)

J'espère que ça aide.

399
shellter

Je pense que cela peut être simplifié en:

grep sysa /etc/passwd || {
    echo "ERROR - The user sysa could not be looked up"
    exit 2
}

ou dans une seule ligne de commande

$ grep sysa /etc/passwd || { echo "ERROR - The user sysa could not be looked up"; exit 2; }

30
Rony

Qu'est-ce que je fais mal?

$(...) contient la valeur , pas le statut de sortie, c'est pourquoi cette approche est incorrecte. Cependant, dans ce cas particulier, cela fonctionne bien car sysa sera imprimé, ce qui rendra la déclaration test vraie. Cependant, if ! [ $(true) ]; then echo false; fi imprimera toujours false car la commande true n'écrit rien sur stdout (même si le code de sortie est 0). C'est pourquoi il doit être reformulé en if ! grep ...; then.

Une alternative serait cat /etc/passwd | grep "sysa" || echo error. Edit: Comme Alex l’a fait remarquer, cat est inutile ici : grep "sysa" /etc/passwd || echo error.

Vous avez trouvé les autres réponses plutôt déroutantes, espérons que cela aidera quelqu'un.

5
Blauhirn

Voici une réponse à titre d'exemple:

Pour vous assurer que les enregistreurs de données sont en ligne, un script cron s'exécute toutes les 15 minutes et se présente comme suit:

#!/bin/bash
#
if ! ping -c 1 SOLAR &>/dev/null
then
  echo "SUBJECT:  SOLAR is not responding to ping" | ssmtp [email protected]
  echo "SOLAR is not responding to ping" | ssmtp [email protected]
else
  echo "SOLAR is up"
fi
#
if ! ping -c 1 OUTSIDE &>/dev/null
then
  echo "SUBJECT:  OUTSIDE is not responding to ping" | ssmtp [email protected]
  echo "OUTSIDE is not responding to ping" | ssmtp [email protected]
else
  echo "OUTSIDE is up"
fi
#

... et ainsi de suite pour chaque enregistreur de données que vous pouvez voir dans le montage à l'adresse http://www.SDsolarBlog.com/montage


Pour votre information, en utilisant &>/dev/null redirige toutes les sorties de la commande, y compris les erreurs, vers /dev/null

(Le conditionnel nécessite uniquement le exit status de la commande ping.)

Toujours pour votre information, notez que, puisque les travaux cron s'exécutent sous la forme root, il n'est pas nécessaire d'utiliser Sudo ping dans un script cron.

1
SDsolar

Sur les systèmes Unix qui le supporte (pas macOS, semble-t-il):

if getent passwd "$username" >/dev/null; then
    printf 'User %s exists\n' "$username"
else
    printf 'User %s does not exist\n' "$username"
fi 

Cela présente l'avantage d'interroger tout service d'annuaire éventuellement utilisé (YP/NIS ou LDAP, etc.) et le fichier de base de données de mots de passe local.


Le problème avec grep -q "$username" /etc/passwd est que cela donnera un faux positif s'il n'y a pas un tel utilisateur, mais que quelque chose d'autre correspond au modèle. Cela peut se produire s'il existe une correspondance partielle ou exacte quelque part dans le fichier.

Par exemple, dans mon fichier passwd, il y a une ligne disant

build:*:21:21:base and xenocara build:/var/empty:/bin/ksh

Cela provoquerait une correspondance valide sur des éléments tels que cara et enoc etc., même s'il n'y a pas de tels utilisateurs sur mon système.

Pour qu'une solution grep soit correcte, vous devez analyser correctement le fichier /etc/passwd:

if cut -d ':' -f 1 /etc/passwd | grep -qxF "$username"; then
    # found
else
    # not found
fi

... ou tout autre test similaire avec le premier des champs délimités par :-.

1
Kusalananda