Làm cách nào để thoát tập lệnh trong câu lệnh có điều kiện?


50

Tôi đang viết một tập lệnh bash nơi tôi muốn thoát nếu người dùng không root. Các điều kiện hoạt động tốt, nhưng kịch bản không thoát.

[[ `id -u` == 0 ]] || (echo "Must be root to run script"; exit)

Tôi đã thử sử dụng &&thay vì ;nhưng không hoạt động.

Câu trả lời:


50

Bạn có thể làm theo cách này:

[[ $(id -u) -eq 0 ]] || { echo >&2 "Must be root to run script"; exit 1; }

(Biểu thức điều kiện "thông thường" với toán tử nhị phân số học trong câu lệnh đầu tiên) hoặc:

(( $(id -u) == 0 )) || { echo >&2 "Must be root to run script"; exit 1; }

(đánh giá số học cho bài kiểm tra đầu tiên).

Lưu ý sự thay đổi ()-> {}- dấu ngoặc nhọn không sinh ra một khung con. (Tìm kiếm man bash"subshell".)


1
Vui lòng thoát với mã khác 0, ví dụ: exit 1để hiểu quy trình cha mẹ xảy ra sự cố.
SamK

1
Bạn không nên sử dụng [[để so sánh số, sử dụng ((.
Chris Xuống

1
@ChrisDown [[là tốt, miễn là bạn sử dụng -eqthay vì ==.
Let_Me_Be

Đã sửa lỗi điều kiện, thêm phiên bản số học, @ChrisDown.
Mat

2
@Mat Nhân tiện, bạn có thể rút ngắn nó xuống(( EUID )) && ...
Chris Down

21

Các dấu ngoặc đơn xung quanh các lệnh đó tạo ra một lớp con . Tiếng vang của subshell của bạn "Phải là root để chạy script" và sau đó bạn nói với subshell để thoát (mặc dù nó đã có rồi, vì không còn lệnh nào nữa). Cách dễ nhất để khắc phục có lẽ là chỉ sử dụng một if:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi

Vì vậy, không có cách nào để làm điều này với một lớp lót?
Hội trường Garrett

1
logic của bạn là ngược. trong ví dụ của bạn, nếu id -u == 0, trong đó sẽ có nghĩa là bạn root. Bạn muốn [[ $(id -u) != 0 ]]; then.
Tim Kennedy

4
Nếu bạn / phải / có một lớp lót, hãy thử kích thước này: [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;Cũng lưu ý $UID, giúp tiết kiệm quá trình sinh sản. Tôi nghĩ bạn thậm chí có thể thích $EUID.
janmoesen

1
@janmoesen, điểm tốt. Và trong khi Midi có một biến có giá trị số : ((UID)) && echo 'You have to be root.' && exit 1.
manatwork

3
@janmoesen: lưu ý rằng việc sử dụng logic nghịch đảo như vậy sẽ khiến tập lệnh set -ehủy bỏ. Một giải pháp cho vấn đề đó là [ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true.
sam hocevar

2

Với bash :

[ $UID -ne 0 ] && echo "Must be root to run script" && exit 1

Điều đó sẽ không thoát nếu echothất bại (ví dụ vì thiết bị xuất chuẩn không thể ghi được).
Stéphane Chazelas

1

Chân đế xung quanh ||&&không bắt buộc vì đây là những liên kết đúng. Hai biểu thức sau là tương đương:

expr1 || expr2 && expr3
expr1 || { expr2 && expr3 }

Vì vậy, &&thay vì ;sẽ làm việc tốt, như echosẽ trở lại đúng.

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1

1
Mặc dù tất cả mọi thứ bạn nói là chính xác, đây là một mô hình không tốt để tìm hiểu, bởi vì bạn đang dựa vào giá trị trả về của expr2. Bạn có chắc chắn rằng echo sẽ luôn trả về trạng thái thoát 0 không? Ý tưởng tốt hơn là nhóm các câu lệnh với dấu ngoặc nhọn và dấu hai chấm. Đây là một cạm bẫy phổ biến đến nỗi nó có mục riêng của nó trong BashPit thác: mywiki.wooledge.org/BashPit thác # cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm

1
@Flimm: Tôi không đồng ý rằng đó là một mô hình xấu. Rõ ràng, việc sử dụng nó phụ thuộc vào từng trường hợp và cũng phụ thuộc vào kiến ​​thức của bạn về các giá trị trả về mà bạn sẽ nhận được. Trong trường hợp này, tôi chắc chắn rằng echo sẽ trả về 0 99,999% số lần và nếu nó bị lỗi ghi (trường hợp duy nhất nó sẽ không trả về 0) thì có vấn đề lớn hơn expr này. Cũng có trường hợp BẠN đang tạo ra các giá trị trả về, vì vậy không, đó không phải là "mẫu xấu" theo tôi.
ata

Tôi cũng sẽ thêm, giống như nó nói trong wiki, rằng bạn nên sử dụng nó nếu chắc chắn hiểu được đánh giá C. Dù sao, một thử nghiệm nhỏ sẽ xóa tan mọi sự mơ hồ.
ata

0

điều này có thể giúp bạn, trong bash

[oracle@rac1 ~]$ which bash
/bin/bash
[oracle@rac1 ~]$ cat test1.sh
if [ `id -u` != 0 ]
then
echo "Must be root to run the script
 "
exit
fi

3
Điều này đã được trả lời và chấp nhận. Ngoài ra, câu trả lời của bạn gần giống với những gì đã được đăng.
malawlawns

@malawlawns, câu trả lời đó, trái với những câu hỏi khác có giá trị là có thể di chuyển được với tất cả các shell giống như Bourne (sẽ tốt hơn nếu lỗi xuất ra trên stderr, trạng thái thoát là khác không và thay thế lệnh được trích dẫn )
Stéphane Chazelas
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.