Làm thế nào để kiểm tra nếu một lệnh thành công?


234

Có cách nào để kiểm tra nếu có lỗi trong khi thực hiện lệnh không?

Thí dụ :

test1=`sed -i "/:@/c connection.url=jdbc:oracle:thin:@$ip:1521:$dataBase" $search`
valid $test1

function valid () {
  if $test -eq 1; then
    echo "OK"
    else echo "ERROR" 
  fi
}

Tôi đã thử làm điều đó nhưng có vẻ như nó không hoạt động. Tôi không làm thế nào để làm điều đó.


9
Thích $ (foo) hơn backticks `foo` , vì bạn có thể lồng nó và dễ dàng hơn để phân biệt với dấu nháy đơn.
người dùng không xác định

1
BTW, bạn cần xác định hàm ( valid) trước khi gọi.
wjandrea

Câu trả lời:


344

Giá trị trả lại được lưu trữ trong $?. 0 chỉ sự thành công, những người khác chỉ ra lỗi.

some_command
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

Giống như bất kỳ giá trị văn bản nào khác, bạn có thể lưu trữ nó trong một biến để so sánh trong tương lai:

some_command
retval=$?
do_something $retval
if [ $retval -ne 0 ]; then
    echo "Return code was not zero but $retval"
fi

Đối với các toán tử so sánh có thể, xem man test.


Thật tuyệt ... tôi có thể giữ lỗi đầu ra không ?? !! , bởi vì trong trường hợp này tôi có 2 lỗi: lỗi lệnh "văn bản" ex, không tìm thấy tệp và lỗi "văn bản" của tôi, ví dụ trong trường hợp này không thành công
moata_u

@moata_u: bạn có thể lưu trữ giá trị trong một biến như trong câu trả lời của tôi.
Lekensteyn

@moata_u: Bạn cần đặt a ;trước elsefi: `if ...; sau đó ...; khác ...; fi
Lekensteyn

4
Đây là một cách sử dụng vô dụngtest .
David Foerster

1
@Blauhirn [ $? ](hoặc tương đương, test $?) không hoạt động vì $?ước tính thành một số (0, 1, v.v.) không phải là null. Xem các tài liệu chotest : "Nếu EXPRESSION bị bỏ qua, 'test' trả về false. Nếu EXPRESSION là một đối số duy nhất, 'test' trả về false nếu đối số là null và ngược lại."
Lekensteyn

87

Nếu bạn chỉ cần biết lệnh thành công hay thất bại, đừng bận tâm kiểm tra $?, chỉ cần kiểm tra trực tiếp lệnh. Ví dụ:

if some_command; then
    printf 'some_command succeeded\n'
else
    printf 'some_command failed\n'
fi

Và việc gán đầu ra cho một biến không làm thay đổi giá trị trả về (tốt, trừ khi nó hoạt động khác đi khi thiết bị xuất chuẩn không phải là thiết bị đầu cuối).

if output=$(some_command); then
    printf 'some_command succeded, the output was «%s»\n' "$output"
fi

http://mywiki.wooledge.org/BashGuide/TestsAndCond điều kiện giải thích ifchi tiết hơn.


Điều gì sẽ xảy ra nếu bạn muốn làm một cái gì đó ngoài việc phân nhánh như lưu trữ boolean cho dù nó thất bại hay không thành .ini? Sau đó, biến đầu ra của bạn không làm điều đó, nhưng $?thực tế, vì vậy bạn không chính xác khi nói rằng kiểm tra lệnh trực tiếp là hoàn toàn tốt hơn.
Timothy Swan

Việc gán đầu ra cho một biến có thể thay đổi giá trị trả về khi một người sử dụng locallệnh, tức là local foo=$(false); echo $?;tạo ra 0trên đầu ra. Nhưng localchỉ có liên quan bên trong các chức năng bash.
Cromax

26
command && echo OK || echo Failed

Nếu commandtrả về lỗi trên màn hình, làm thế nào để ẩn nó?
Sigur

Nếu commandviết lỗi ra stderr, bạn có thể sử dụng biểu mẫu command 2> /dev/null && echo OK || echo Failed. Các 2> /dev/nullchuyển hướng đầu ra stderr đến /dev/null. Tuy nhiên, một số tiện ích sẽ ghi lỗi vào thiết bị xuất chuẩn (mặc dù đây là thông lệ xấu). Trong trường hợp này, bạn có thể bỏ qua 2 từ chuyển hướng, nhưng bạn sẽ mất bất kỳ đầu ra nào từ lệnh. Phương pháp kiểm tra thành công này tốt cho logic đơn giản nhưng đối với hành vi phức tạp hơn, tốt nhất là kiểm tra $?thành công của lệnh hoặc sử dụng ifphương thức khối được nêu trong câu trả lời của @ geirha.
Bender vĩ đại nhất

17

$? phải chứa trạng thái thoát của lệnh trước đó, không có lỗi nào.

Vì vậy, một cái gì đó như;

cd /nonexistant
if [ $? -ne 0 ]
then
    echo failed
else
    echo success!
fi

trong hầu hết các trường hợp, việc sử dụng && xây dựng để xâu chuỗi các lệnh cần phụ thuộc vào nhau dễ dàng hơn. Vì vậy, cd /nonexistant && echo success!sẽ không lặp lại thành công vì lệnh bị phá vỡ trước &&. Hệ quả của điều này là | |, trong cd /nonexistant || echo fail đó echo sẽ thất bại vì cd thất bại. (điều này trở nên hữu ích nếu bạn sử dụng một cái gì đó như | | exit, sẽ kết thúc tập lệnh nếu lệnh trước đó không thành công.)


Thật tuyệt ... tôi có thể giữ lỗi đầu ra không ?? !! , bởi vì trong trường hợp này tôi có 2 lỗi: lỗi lệnh "văn bản" ex, không tìm thấy tệp và lỗi "văn bản" của tôi, ví dụ trong trường hợp này không thành công
moata_u


5
command && echo $? || echo $?

Ý bạn là command; echo $?sao?
Javier Buzzi

Không, dòng của tôi là chính xác, nó đưa ra mã kết quả thực tế dưới dạng số bất kể thành công hay thất bại.
modrobert

1
Ok, vui lòng giải thích sự khác biệt của những điều này với tôi: true && echo $? || echo $?/ true; echo $?false && echo $? || echo $?/ false; echo $?- bạn sẽ tìm thấy, họ làm điều tương tự chính xác: D
Javier Buzzi

Có, kết quả tương tự nhưng không có điều kiện. Câu hỏi ban đầu được hỏi là "Làm thế nào để kiểm tra xem một lệnh có thành công không?", Điều này dựa trên các câu trả lời trước đó. Tôi đoán một ví dụ tốt hơn sẽ là:command && echo "success: $?" || echo "fail: $?"
modrobert

5

Cần lưu ý rằng if...then...fi&&/ ||loại giao dịch tiếp cận với trạng thái thoát được trả về bằng lệnh chúng tôi muốn kiểm tra (0 khi thành công); tuy nhiên, một số lệnh không trả về trạng thái thoát khác không nếu lệnh không thành công hoặc không thể xử lý đầu vào. Điều này có nghĩa là các cách tiếp cận thông thường if&&/ ||sẽ không hoạt động đối với các lệnh cụ thể đó.

Chẳng hạn, trên Linux GNU filevẫn tồn tại với 0 nếu nó nhận được tệp không tồn tại dưới dạng đối số và findkhông thể xác định vị trí người dùng tệp được chỉ định.

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

Trong các trường hợp như vậy, một cách tiềm năng mà chúng ta có thể xử lý tình huống là bằng cách đọc stderr/ stdintin nhắn, ví dụ: những cách được trả về bằng filelệnh hoặc phân tích đầu ra của lệnh như trong find. Đối với mục đích đó, casetuyên bố có thể được sử dụng.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found

(Đây là một bài đăng lại câu trả lời của riêng tôi về câu hỏi liên quan tại unix.stackexchange.com )


1

Như đã đề cập trong nhiều câu trả lời khác, một bài kiểm tra đơn giản $?sẽ làm, như thế này

if [ $? -eq 0 ]; then something; fi

Nếu bạn muốn kiểm tra xem lệnh có bị lỗi hay không , bạn có thể sử dụng phiên bản ngắn hơn trong bash(nhưng có lẽ là quá mức) như sau:

if (($?)); then something; fi

Điều này hoạt động bằng cách sử dụng (( ))chế độ số học, vì vậy nếu lệnh được trả về success, tức là $? = 0kiểm tra sẽ đánh giá ((0))kiểm tra nào false, nếu không nó sẽ trả về true.

Để kiểm tra thành công , bạn có thể sử dụng:

if ! (($?)); then something; fi

nhưng nó đã không ngắn hơn nhiều so với ví dụ đầu tiên.


1
phê bình mang tính xây dựng?
afuna


-2

if [$ (lệnh)]; sau đó lặp lại "thành công"; fi


3
truethành công trong if [ $(true) ]; then echo "succeed"; finhưng succeedkhông được in. Trong thực tế điều này không bao giờ kiểm tra nếu commandthành công. Nó chỉ nên sử dụng if commandnhư trong bài của geirha . $( )lệnh thay thế . [ ]là một biểu thức có điều kiện . Vắng mặt tách từ và tên tập tin mở rộng , điều này về cơ bản kiểm tra nếu commandcó đầu ra.
Eliah Kagan
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.