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
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.
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; }
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.
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
.
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 :
-.