Operator "dan" untuk pernyataan "jika" di Bash

168

Saya mencoba membuat skrip Bash sederhana untuk memeriksa apakah situs webnya rusak dan untuk beberapa alasan operator "dan" tidak berfungsi:

#!/usr/bin/env bash

WEBSITE=domain.com
SUBJECT="$WEBSITE DOWN!"
EMAILID="[email protected]"
STATUS=$(curl -sI $WEBSITE | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s $WEBSITE | grep -o "string_to_search")
VALUE="string_to_search"

if [ $STATUS -ne 200 ] && [[ "$STRING" != "$VALUE" ]]; then
    echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" $EMAILID
fi

Operator "-a" juga tidak berfungsi:

if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]

Bisakah Anda juga memberi saran kapan harus menggunakan:

  • kurung kotak tunggal dan ganda
  • kurung

?

HTF
sumber
3
Bisakah Anda lebih tepatnya tentang apa yang "tidak berhasil"? Apakah Anda memiliki pesan kesalahan tertentu, atau apakah tidak hanya memberikan hasil yang diharapkan?
Julien Vivenot
Saya sebenarnya menerima "operator yang tidak terduga diharapkan" sehingga sepertinya mengutip membantu
HTF
-abermuka dua. Saat digunakan dengan testperintah gaya shell Bourne , alias [, artinya and. Ketika digunakan sebagai ekspresi kondisional maka ia sedang menguji untuk melihat apakah ada file. Ya itu membingungkan, sebaiknya dihindari.
cdarke

Jawaban:

254

Apa yang Anda miliki harus berfungsi, kecuali ${STATUS}kosong. Mungkin akan lebih baik untuk dilakukan:

if ! [ "${STATUS}" -eq 200 ] 2> /dev/null && [ "${STRING}" != "${VALUE}" ]; then

atau

if [ "${STATUS}" != 200 ] && [ "${STRING}" != "${VALUE}" ]; then

Sulit dikatakan, karena Anda belum menunjukkan kepada kami apa yang salah dengan skrip Anda.

Pendapat pribadi: tidak pernah digunakan [[. Ini menekan pesan kesalahan penting dan tidak mudah dibawa ke shell yang berbeda.

William Pursell
sumber
2
Jika STATUSkosong, kode dari @HTF akan gagal -ne: unary operator expected. Dalam kasus Anda, itu akan gagal integer expression expected, bukan?
Julien Vivenot
1
Aku mengerti itu. Tetapi Anda menyoroti masalah yang $STATUSmungkin kosong dan menyarankan solusi (mengutipnya). Solusi Anda masih gagal dengan yang kosong STATUS, itu yang saya maksud.
Julien Vivenot
1
@ jvivenot Anda benar. (Tanggapan saya terhadap komentar Anda dibuat sebelum Anda mengedit komentar Anda, ketika komentar Anda hanya membaca "kode ... akan gagal". Solusi sederhana adalah dengan menggunakan ${STATUS:-0". Akan mengedit.
William Pursell
Maaf, hasil edit Anda masih tidak berfungsi. Misalnya: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo footidak menampilkan foo, meskipun seharusnya (kosong berbeda dari 13). Apa yang pertama kali Anda sarankan, ${STATUS:-0}terlihat jauh lebih baik.
Julien Vivenot
@ jvivenot Menggunakan ${STATUS:-0}akan gagal jika STATUS=foo, tetapi ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo fooberfungsi. IMO, lebih baik untuk menghindari -eqdan menggunakannya !=.
William Pursell
28

Coba ini:

if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then
BrenanK
sumber
bekerja untukku. Saya pikir mungkin ada lebih dari satu cara tetapi saya puas dengan ini untuk saat ini.
Kushal Ashok
27

Coba ini:

if [ ${STATUS} -ne 100 -a "${STRING}" = "${VALUE}" ]

atau

if [ ${STATUS} -ne 100 ] && [ "${STRING}" = "${VALUE}" ]
AnshBikram
sumber
plus untuk contoh terbersih
Pawel Cioch
12

Mengutip:

Operator "-a" juga tidak berfungsi:

jika [$ STATUS -ne 200] -a [["$ STRING"! = "$ VALUE"]]

Untuk penjelasan yang lebih terperinci: [dan ]bukan kata-kata yang dipesan Bash. Kata ifkunci memperkenalkan persyaratan untuk dievaluasi oleh suatu pekerjaan (kondisi tersebut benar jika nilai pengembalian pekerjaan itu 0salah atau sebaliknya).

Untuk tes sepele, ada testprogram ( man test).

Seperti beberapa menemukan garis seperti if test -f filename; then foo bar; fi, dll. Menjengkelkan, pada sebagian besar sistem Anda menemukan program yang disebut [yang sebenarnya hanya merupakan tautan ke testprogram. Ketika testdipanggil sebagai [, Anda harus menambahkan ]argumen posisi terakhir.

Jadi if test -f filenamepada dasarnya sama (dalam hal proses menelurkan) sebagai if [ -f filename ]. Dalam kedua kasus testprogram akan dimulai, dan kedua proses harus berperilaku identik.

Inilah kesalahan Anda: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]akan menguraikan ifbeberapa pekerjaan, pekerjaan menjadi segalanya kecuali pekerjaan ifitu sendiri. Pekerjaan itu hanya perintah sederhana (Bash berbicara untuk sesuatu yang menghasilkan satu proses tunggal), yang berarti kata pertama ( [) adalah perintah dan sisanya argumen posisinya. Ada argumen tersisa setelah yang pertama] .

Juga tidak, [[memang kata kunci Bash, tetapi dalam kasus ini hanya diuraikan sebagai argumen perintah normal, karena itu bukan di depan perintah.

Jo So
sumber