Nắm bắt mã thoát của lệnh thoát


10

Tôi có điều này trong một kịch bản bash:

exit 3;

exit_code="$?"

if [[ "$exit_code" != "0" ]]; then
    echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
    exit "$exit_code";
fi

Có vẻ như nó sẽ thoát ngay sau lệnh exit, điều này có ý nghĩa. Tôi đã tự hỏi là có một số lệnh đơn giản có thể cung cấp một mã thoát mà không cần thoát ra ngay lập tức?

Tôi sẽ đoán:

exec exit 3

nhưng nó đưa ra một thông báo lỗi : exec: exit: not found. Tôi có thể làm gì? :)


1
Vâng exec exit 3không phải là bueno, tôi nhận được"exec: exit: not found"

7
Tôi không hiểu câu hỏi. Tại sao không thiết lập exit_code=3và loại bỏ exit 3hoàn toàn dòng?
wjandrea

@wjandrea là một câu hỏi mang tính khái niệm hơn là thực tế

2
Nó vẫn không có ý nghĩa với tôi. Tại sao sẽ có một mã thoát nếu bạn không thực sự thoát?
Barmar

1
@Barmar mỗi quá trình có một mã thoát. Hầu hết những người cố gắng trả lời câu hỏi đang diễn giải câu hỏi có nghĩa là "tôi có thể thay thế 'thoát 3' bằng gì trong tập lệnh để nó đặt $?biến nhưng không thoát khỏi tập lệnh này "?
icarus

Câu trả lời:


32

Nếu bạn có một tập lệnh chạy một số chương trình và xem trạng thái thoát của chương trình (với  $?) và bạn muốn kiểm tra tập lệnh đó bằng cách thực hiện một số nguyên nhân $?được đặt thành một giá trị đã biết (ví dụ  3:), chỉ cần làm

(exit 3)

Các dấu ngoặc đơn tạo ra một vỏ phụ. Sau đó, exitlệnh làm cho lớp vỏ phụ đó thoát ra với trạng thái thoát được chỉ định.


Ngoài ra, với mục đích gỡ lỗi, việc cài đặt exit_code="3"để thử nghiệm rất đơn giản
Centimane


12

exitlà một bash tích hợp, vì vậy bạn không thể exec. Hướng dẫn sử dụng của mỗi bash :

Trạng thái thoát của Bash là trạng thái thoát của lệnh cuối cùng được thực thi trong tập lệnh. Nếu không có lệnh nào được thực thi, trạng thái thoát là 0.

Đặt tất cả những thứ này lại với nhau, tôi muốn nói rằng tùy chọn duy nhất của bạn là lưu trữ trạng thái thoát mong muốn của bạn trong một biến và sau đó exit $MY_EXIT_STATUSkhi thích hợp.


hmmm, bạn nghĩ gì về ý tưởng của @ G-man?

2
Có lẽ tôi đã hiểu nhầm những gì bạn đang cố gắng thực hiện. Nếu bạn chỉ đang cố gắng thiết lập $?(mặc dù tôi không thực sự chắc chắn tại sao bạn lại như vậy), thì đó dường như là một câu trả lời chắc chắn. Nếu bạn chỉ muốn đặt nó thành một số giá trị không thành công, falselà một tùy chọn khác.
solarshado

10

Bạn có thể viết một hàm trả về trạng thái được cung cấp dưới dạng đối số hoặc 255nếu không có. (Tôi gọi nó retlà "trả lại" giá trị của nó.)

ret() { return "${1:-255}"; }

và sử dụng retthay cho cuộc gọi của bạn đến exit. Điều này là tránh sự không hiệu quả của việc tạo lớp vỏ phụ trong câu trả lời hiện được chấp nhận.

Một số phép đo.

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?'

trên máy của tôi mất khoảng 3,5 giây.

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?'

trên máy của tôi mất khoảng 0,051 giây, nhanh hơn 70 lần. Đưa vào xử lý mặc định vẫn để nó nhanh hơn 60 lần. Rõ ràng vòng lặp có một số chi phí. Nếu tôi thay đổi phần thân của vòng lặp thành :hoặc truesau đó thời gian được giảm một nửa thành 0,025, thì một vòng lặp hoàn toàn trống là cú pháp không hợp lệ. Thêm ;:vào vòng lặp cho thấy lệnh tối thiểu này mất 0,007 giây, do đó, chi phí vòng lặp là khoảng 0,008. Trừ chi phí này từ hai thử nghiệm cho thấy retgiải pháp nhanh hơn 100 lần.

Rõ ràng đây là một phép đo tổng hợp, nhưng mọi thứ cộng lại. Nếu bạn làm mọi thứ chậm hơn 100 lần so với mức cần thiết thì bạn sẽ có hệ thống chậm. 0,0


2
@iBug Không cần thêm dung lượng.
icarus

Điểm hay về sự kém hiệu quả của việc tạo lớp vỏ phụ. Tôi đã đọc được rằng một số shell có thể đủ thông minh để tối ưu hóa fork trong các trường hợp như thế này, nhưng bash đó không phải là một trong số chúng.
G-Man nói 'Phục hồi Monica'

3

Về exec exit 3... nó sẽ cố chạy một lệnh bên ngoài được gọi exit, nhưng không có lệnh nào , vì vậy bạn gặp lỗi. Nó phải là một lệnh bên ngoài thay vì một lệnh được tích hợp vào shell, vì exec thay thế hoàn toàn shell. Điều đó cũng có nghĩa là ngay cả khi bạn có lệnh bên ngoài được gọi exit, exec exit 3sẽ không quay lại để tiếp tục tập lệnh shell của bạn, vì shell sẽ không còn nữa .


1
Tôi đoán bạn có thể làm exec bash -c "exit 3", nhưng hiện tại tôi không thể nghĩ ra bất kỳ lý do nào để làm điều đó trái ngược với chỉ exit 3.
David Z

1
@DavidZ, trong mọi trường hợp, exec'ing hoặc just exit' ing sẽ dừng tập lệnh, điều này dường như không giống như những gì câu hỏi muốn.
ilkkachu

3

Bạn có thể làm điều này với Awk:

awk 'BEGIN{exit 9}'

Hoặc Sed:

sed Q9 /proc/stat

... hoặc với một cái vỏ:sh -c 'exit 9'
ilkkachu

1
@ilkkachu nếu bạn định làm điều đó bạn cũng có thể làm (exit 9)câu trả lời được chấp nhận
Steven Penny
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.