Как сделать "если не истинное состояние"?


Я хотел бы иметь echo команда выполняется, когда cat /etc/passwd | grep "sysa" - это неправда.

что я делаю не так?

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

5 ответов:

попробовать

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

grep возвращает true если он находит цель поиска, и false если это не так.

не так false ==true.

if оценка в оболочках разработаны, чтобы быть очень гибким, и много раз не требует цепочек команд (как вы написали).

кроме того, глядя на ваш код, как есть, ваше использование $( ... ) форма cmd-замены заслуживает похвалы, но подумайте о том, что выходит процесс. Попробуй echo $(cat /etc/passwd | grep "sysa") чтобы увидеть, что я имею в виду. Вы можете взять это дальше, используя -c (count) опция для grep, а затем сделать if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then который работает, но довольно старая школа.

но вы можете использовать новейшие функции оболочки (арифметическая оценка), такие как

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

что также дает вам преимущество использования операторов сравнения на основе c-lang,==,<,>,>=,<=,% и, возможно, некоторые другие.

в этом случае, согласно комментарию Оруэллофила, арифметика оценка может быть урезана еще больше, например

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

или

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

наконец, есть награда назвал Useless Use of Cat (UUOC). :- ) Некоторые люди будут прыгать вверх и вниз и плакать gothca! Я просто скажу, что grep может принимать имя файла в своей cmd-строке, так зачем вызывать дополнительные процессы и конструкции труб, когда вам это не нужно? ; -)

я надеюсь, что это помогает.

Я думаю, что это можно упростить в:

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

или в одной командной строке

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

что я делаю не так?

$(...) держит стоимостью, а не статус выхода, поэтому этот подход неверен. Однако, в данном конкретном случае, это действительно работает, потому что sysa будет напечатано, что делает тестовый оператор сбывается. Однако,if ! [ $(true) ]; then echo false; fi всегда будет печатать false - за true команда ничего не пишет в stdout (даже если код выхода равен 0). Вот почему его нужно перефразировать if ! grep ...; then.

альтернативой было бы cat /etc/passwd | grep "sysa" || echo error. Редактировать: как отметил Алекс,кошка здесь бесполезна:grep "sysa" /etc/passwd || echo error.

нашел другие ответы довольно запутанными, надеюсь, это кому-то поможет.

на системах Unix, которые поддерживают его (не macOS, кажется):

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

это имеет то преимущество, что он будет запрашивать любую службу каталогов, которая может использоваться (YP/NIS или LDAP и т. д.) и локальный файл базы данных паролей.


вопрос с grep -q "$username" /etc/passwd это то, что он даст ложное срабатывание, когда нет такого пользователя, но что-то еще соответствует шаблону. Это может произойти, если есть частичное или точное совпадение где-то в другом месте файл.

например, в моем passwd файл, есть строка, говорящая

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

это спровоцировало бы действительное совпадение на таких вещах, как cara и enoc etc., хотя таких пользователей в моей системе нет.

на grep решение будет правильным, вам нужно будет правильно разобрать /etc/passwd file:

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

... или любой другой подобный тест против первых : - поля с разделителями.

вот ответ в качестве примера:

для того, чтобы убедиться, что регистраторы данных находятся в сети a cron скрипт запускается каждые 15 минут, который выглядит так:

#!/bin/bash
#
if ! ping -c 1 SOLAR &>/dev/null
then
  echo "SUBJECT:  SOLAR is not responding to ping" | ssmtp abc@def.com
  echo "SOLAR is not responding to ping" | ssmtp 4151112222@txt.att.com
else
  echo "SOLAR is up"
fi
#
if ! ping -c 1 OUTSIDE &>/dev/null
then
  echo "SUBJECT:  OUTSIDE is not responding to ping" | ssmtp abc@def.com
  echo "OUTSIDE is not responding to ping" | ssmtp 4151112222@txt.att.com
else
  echo "OUTSIDE is up"
fi
#

...и так далее для каждого регистратора данных, который вы можете увидеть в монтаже в http://www.SDsolarBlog.com/montage


FYI, используя &>/dev/null перенаправляет все выходные данные команды, включая ошибки, на /dev/null

(условный требует только exit status на )

также FYI, обратите внимание, что с cron задания выполняются как root нет необходимости использовать sudo ping на cron сценарий.