2012-05-11 20 views
197

Chciałbym wykonać polecenie echo, gdy cat /etc/passwd | grep "sysa" nie jest prawdziwe.Jak zrobić "jeśli nie prawdziwy stan"?

Co robię źle?

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

Czy '!' Nie powinno znajdować się w nawiasach? tj. [! WYRAŻ] ' – acraig5075

+5

@ acraig5075 jest ważny tak czy inaczej, ale nie ma potrzeby, aby polecenie testowe (co jest nawiasami) w ogóle w tym zestawieniu. –

Odpowiedz

296

spróbować

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

grep powraca true jeżeli stwierdzi celu szukania i false czy nie.

Więc NIE false == true.

if ewaluacja w powłokach ma być bardzo elastyczna i wiele razy nie wymaga łańcuchów poleceń (jak napisałeś).

Również patrząc na twój kod, jak jest, należy pochwalić korzystanie z formy zastępczej cmd, ale pomyśl o tym, co wychodzi z procesu. Wypróbuj echo $(cat /etc/passwd | grep "sysa"), aby zobaczyć, co mam na myśli. Możesz to zrobić dalej, używając opcji -c (liczenie) do grep, a następnie wykonaj if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then, która działa, ale jest raczej stara.

ALE, można korzystać z najnowszych funkcji powłoki (ocena arytmetyka) jak

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

który także daje korzyści z wykorzystaniem c-LANG operatorów porównania oparte ==,<,>,>=,<=,% i być może kilku innych.

W tym przypadku, za komentarz przez Orwellophile, ocena arytmetyka może być porównaniu dół jeszcze bardziej, jak

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

LUB

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

Wreszcie istnieje nagroda zwany w Useless Use of Cat (UUOC). :-) Niektórzy ludzie będą podskakiwać i płakać gothca! Powiem tylko, że grep może przyjmować nazwę pliku na linii cmd, więc po co wywoływać dodatkowe procesy i konstrukcje rur, kiedy nie musisz? ;-)

Mam nadzieję, że to pomoże.

+1

To wszystko jest dość głupie, z mojej odpowiedzi na o wiele trudniejsze (pytanie) [http: // stackoverflow.com/a/30400327/912236] 'grep"^$ user: "/ etc/passwd" byłoby lepszym sposobem wyszukiwania/etc/passwd incydentalnie - 'grep -v' gdzie * -v * odwraca wyszukiwanie, jeśli chciałem uniknąć bałaganu || – Orwellophile

+0

tak, dobrze rozwiązuje problem najskuteczniej, a następnie odpowiada na konkretne pytanie. Próbowałem odpowiedzieć na konkretne pytanie. Dzięki za twoje pomysły. Powodzenia wszystkim. – shellter

+1

nie odbierając twoich odpowiedzi, całkiem im się podobało. Właśnie przez to wrzuciłem poprawnie ograniczoną kontrolę nazwy użytkownika, w przeciwnym razie, jeśli OP rzeczywiście wyszuka "sys" lub "somesuch", dostanie niespodziankę. jeszcze jeden na drogę? '(($ (plik cat | grep regex | wc -l)? 0: 1))' – Orwellophile

29

Myślę, że może być uproszczone do:

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

lub w jednym wierszu poleceń

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

+3

Fajnie, ale ja wolę odpowiedź pana skorupiaka, ponieważ jest "udokumentowana", jest bardziej "czytelna" w intencji programisty. –

+1

Podoba mi się ta wersja. Co powiesz na dodanie '1> i 2' na końcu' echa', aby wydrukować na 'stderr'? – Julien

+2

@ 0zkrPM Ale wersja skorupki nie działa w powłoce Bourne'a. Otrzymasz '!: Not found' – ceving

2

Co robię źle?

$(...) przechowuje wartość , a nie stan wyjścia, dlatego takie podejście jest błędne. Jednak w tym konkretnym przypadku rzeczywiście działa, ponieważ zostanie wydrukowane sysa, co sprawia, że ​​wyrażenie testowe staje się prawdą.Jednak if ! [ $(true) ]; then echo false; fi zawsze będzie drukować false, ponieważ polecenie true nie zapisuje niczego na standardowe wyjście (nawet jeśli kod wyjścia ma wartość 0). Dlatego musi zostać ponownie sformułowana na if ! grep ...; then.

Alternatywą byłoby cat /etc/passwd | grep "sysa" || echo error. Edytuj, jak wskazał Alex, cat is useless here: grep "sysa" /etc/passwd || echo error.

Znaleziono inne odpowiedzi raczej mylące, mam nadzieję, że to pomaga komuś.

+1

lub "grep" sysa "/ etc/passwd || echo error' –

+0

@AlexYaroshevich tak, masz rację, dodałem, że – Blauhirn

1

W systemach Unix, który je obsługuje (nie wydaje MacOS):

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

Ma to tę zaletę, że będzie żadnej kwerendy usługi katalogowej, które mogą być w użyciu (YP/NIS lub LDAP etc.) i lokalny plik bazy danych haseł.


Problem z grep -q "$username" /etc/passwd jest to, że dają fałszywie dodatni, gdy nie ma takiego użytkownika, ale coś innego pasuje do wzorca. Może się to zdarzyć, jeśli w pliku występuje dopasowanie częściowe lub ścisłe.

Na przykład w moim pliku passwd, istnieje linia mówiąc

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

ta sprowokuje ważny mecz na rzeczy jak cara i enoc itp, chociaż nie ma takich użytkowników na moim systemie.

rozwiązania grep być poprawne, trzeba będzie poprawnie analizować plik /etc/passwd:

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

... lub inny podobny test przed pierwszym z : pól -delimited.

+0

@SDsolar Twój kod prawdopodobnie nie jest wykonywany przez 'bash' w takim przypadku. – Kusalananda

1

Oto odpowiedź tytułem przykładu:

W celu upewnienia się, rejestratory danych są miesiacu cron skrypt kursuje co 15 minut, które wygląda następująco:

#!/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 
# 

... i tak dalej dla każdego rejestratora danych, które można zobaczyć w montażu na http://www.SDsolarBlog.com/montage


FYI, używając &>/dev/null przekierowuje wszystkie wyjścia z komendy, w tym błędów, aby /dev/null

(Warunkowe wymaga jedynie exit status dowodzenia w ping)

też FYI pamiętać, że od cron zadania uruchamiane jako root istnieje nie trzeba używać skryptu sudo ping w skrypcie cron.

Powiązane problemy