Một nhà điều hành và một người khai thác cho một người khác nếu tuyên bố của người Viking trong Bash


168

Tôi đang cố gắng tạo một tập lệnh Bash đơn giản để kiểm tra xem trang web có bị hỏng hay không và vì lý do nào đó, toán tử "và" không hoạt động:

#!/usr/bin/env bash

WEBSITE=domain.com
SUBJECT="$WEBSITE DOWN!"
EMAILID="an@email.com"
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

Toán tử "-a" cũng không hoạt động:

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

Bạn cũng có thể vui lòng tư vấn khi sử dụng:

  • dấu ngoặc đơn và đôi
  • dấu ngoặc đơn

?


3
Bạn có thể vui lòng chính xác hơn về những gì "không hoạt động"? Bạn có một thông báo lỗi cụ thể, hoặc đơn giản là không cung cấp đầu ra dự kiến?
Julien Vivenot

Tôi thực sự đã nhận được "kỳ vọng nhà điều hành đơn lẻ" vì vậy có vẻ như trích dẫn giúp
HTF

-acó sự trùng lặp. Khi được sử dụng với testlệnh kiểu Bourne shell , aka [, nó có nghĩa and. Khi được sử dụng như một biểu thức có điều kiện thì nó đang kiểm tra xem một tệp có tồn tại không. Có nó là khó hiểu, tốt nhất nên tránh.
cdarke

Câu trả lời:


254

Những gì bạn có nên làm việc, trừ khi ${STATUS}trống rỗng. Có lẽ sẽ tốt hơn để làm:

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

hoặc là

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

Thật khó để nói, vì bạn đã không cho chúng tôi thấy chính xác những gì đang xảy ra với kịch bản của bạn.

Ý kiến ​​cá nhân: không bao giờ sử dụng [[. Nó ngăn chặn các thông báo lỗi quan trọng và không thể di chuyển đến các shell khác nhau.


2
Nếu STATUStrống, mã từ @HTF sẽ thất bại -ne: unary operator expected. Trong trường hợp của bạn, nó sẽ thất bại integer expression expected, phải không?
Julien Vivenot

1
Tôi hiểu điều đó. Nhưng bạn nhấn mạnh vấn đề $STATUScó thể trống và đề xuất giải pháp (trích dẫn nó). Giải pháp của bạn vẫn thất bại với một sản phẩm nào STATUS, đó là tất cả những gì tôi muốn nói.
Julien Vivenot

1
@jvivenot Bạn có một điểm. (Phản ứng của tôi khi viết phản hồi đã được thực hiện trước khi bạn thay đổi nội dung bình luận của bạn, khi bình luận của bạn chỉ đơn thuần đọc "mã ... sẽ thất bại" dung dịch A đơn giản là để sử dụng. ${STATUS:-0"Will chỉnh sửa..
William Pursell

Xin lỗi, chỉnh sửa của bạn vẫn không hoạt động. Ví dụ: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo fookhông xuất ra foo, mặc dù nó nên (trống khác với 13). Những gì bạn đề nghị đầu tiên, có ${STATUS:-0}vẻ tốt hơn nhiều.
Julien Vivenot

@jvivenot Sử dụng ${STATUS:-0}sẽ thất bại nếu STATUS=foo, nhưng ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo foohoạt động. IMO, tốt hơn là nên tránh -eqvà sử dụng !=.
William Pursell

28

Thử cái này:

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

đã làm cho tôi. Tôi nghĩ có thể có nhiều hơn một cách nhưng tôi hài lòng với điều này cho đến bây giờ.
Kushal Ashok

27

Thử cái này:

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

hoặc là

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

cộng với ví dụ rõ ràng nhất
Pawel Cioch

12

Trích dẫn:

Toán tử "-a" cũng không hoạt động:

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

Đối với một lời giải thích chi tiết hơn: []không phải là những từ dành riêng của Bash. Các iftừ khóa giới thiệu một điều kiện để được đánh giá bởi một công việc (các điều kiện là đúng nếu giá trị trả về của công việc là 0hay sai khác).

Đối với các bài kiểm tra tầm thường, có testchương trình ( man test).

Như một số dòng tìm thấy if test -f filename; then foo bar; fi, v.v. gây phiền nhiễu, trên hầu hết các hệ thống, bạn tìm thấy một chương trình được gọi [là trên thực tế chỉ là một liên kết tượng trưng đến testchương trình. Khi testđược gọi là as [, bạn phải thêm ]làm đối số vị trí cuối cùng.

Vì vậy, if test -f filenamevề cơ bản là giống nhau (về các quá trình sinh ra) như if [ -f filename ]. Trong cả hai trường hợp, testchương trình sẽ được bắt đầu và cả hai quá trình sẽ hoạt động giống hệt nhau.

Đây là sai lầm của bạn: if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]sẽ phân tích thành if+ một số công việc, công việc là tất cả mọi thứ trừ ifchính nó. Công việc chỉ là một lệnh đơn giản (Bash nói cho một cái gì đó dẫn đến một quy trình duy nhất), có nghĩa là từ đầu tiên ( [) là lệnh và phần còn lại là các đối số vị trí của nó. Có những tranh luận còn lại sau lần đầu tiên] .

Cũng không phải, [[thực sự là một từ khóa Bash, nhưng trong trường hợp này, nó chỉ được phân tích cú pháp như một đối số lệnh thông thường, bởi vì nó không ở phía trước của lệnh.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.