Tránh chạy tập lệnh nếu một biến không được xác định


15

Tôi có một kịch bản giống như:

c=0
for f in */*; do
cp -v "$f" "/myhome/CE$(printf '%0*d' 2 $BATCHNUM)-new-stuctures_extracted/test-$(printf '%0*d' 5 $c)"
c=$((c=c+1))
done

Tuy nhiên, người dùng phải cung cấp một cuộc gọi biến BATCHNUM và nếu không tôi cần buộc tập lệnh này ngừng chạy. Sẽ tốt hơn nếu tôi có thể buộc tập lệnh gọi tập lệnh này dừng quá (hoặc thậm chí tập lệnh số 1 gọi tập lệnh số 2 gọi tập lệnh này).

Câu trả lời:


26

Cách nhanh nhất có lẽ là thêm hai dòng này vào đầu tập lệnh:

set -u # or set -o nounset
: "$BATCHNUM"

Dòng đầu tiên đặt nounsettùy chọn trong trình bao chạy tập lệnh, nó sẽ hủy bỏ nếu bạn cố gắng mở rộng một biến không đặt; cái thứ hai mở rộng $BATCHNUMtrong bối cảnh không hoạt động, để kích hoạt việc hủy bỏ trước khi làm bất cứ điều gì khác.

Nếu bạn muốn một thông báo lỗi hữu ích hơn, thay vào đó bạn có thể viết:

if [[ -z "$BATCHNUM" ]]; then
    echo "Must provide BATCHNUM in environment" 1>&2
    exit 1
fi

Hoặc tương tự.


16

Ở đây bạn muốn kiểm tra BATCHNUMđược thiết lập và không null.

Vỏ POSIX cung cấp một Mở rộng tham số cho công việc này. Chỉ cần thêm dòng này trước khi sử dụng BATCHNUM:

: "${BATCHNUM:?Variable not set or empty}"

hoặc tốt hơn để đặt giá trị mặc định cho BATCHNUMnếu người dùng không cung cấp một giá trị :

: "${BATCHNUM:=3}"

3
[ -n "$BATCHNUM" ] || { kill "$PPID"; exit 1; }
#Unless $BATCHNUM is defined and unempty, ask parent process to exit and exit w/ 1

Điều này sẽ hoạt động trên bash và trong một POSIX sh. Tôi không thích phân biệt giữa các biến rỗng và các biến không xác định (nghĩa là tôi không thích set -u, nhưng đó chỉ là tôi).


2

Những dòng kẻ

if [ -z "$BATCHNUM" ]; then
    exit 2;
fi

kiểm tra xem có sản phẩm nào $BATCHNUM. Với $PPIDbạn có thể làm bất cứ điều gì gây hại cho cha mẹ của bạn ( kill $PPID). Để giết ông bà của bạn, bạn cần lấy id quá trình bằng các cách khác, như xem dữ liệu trong /proc/$PPID.

Tuy nhiên, nếu cha mẹ bạn chết, nó sẽ gửi tín hiệu ( SIGHUP) cho bạn, vì vậy bạn phải bẫy nó trước khi bạn bắt đầu giết bất kỳ ai:

trap '' SIGHUP

Cập nhật: Nếu bạn nghĩ rằng bạn phải giết cha mẹ mình, bạn đã làm sai. Chỉ cần trả lại một mã thoát có ý nghĩa. Tập lệnh cha nên kiểm tra mã trả về của tập lệnh được gọi và phản ứng tương ứng.


1
hơi tàn bạo .... :)
user40780

1

Để kiểm tra nếu BATCHNUMđược xác định và thoát nếu không:

if [ -n "${BATCHNUM-a}" ]; then
  echo >&2 "Fatal error: BATCHNUM not set"
  exit 2
fi

Nếu bạn cũng muốn từ chối trường hợp BATCHNUMtrống, sử dụng ${BATCHNUM:+a}thay vì ${BATCHNUM+a}. Để biết thông tin về ${VARIABLE+TEXT_IF_NULL}cấu trúc mở rộng tham số, xem ví dụ: hướng dẫn bash .

Đừng giết quá trình cha mẹ. Bạn không biết quy trình cha mẹ là gì. Nếu một số tập lệnh gọi tập lệnh này cần hủy bỏ nếu tập lệnh này hủy bỏ, hãy làm cho nó kiểm tra trạng thái thoát của tập lệnh này. Ví dụ: trong tập lệnh # 2:

script3 || exit $?

hoặc sử dụng set -eđể hủy bỏ tập lệnh nếu bất kỳ lệnh nào trả về trạng thái lỗi (không khác).

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.