Bash: phát hiện thực thi vs nguồn trong một kịch bản?


19

Tôi có một tập lệnh nằm rải rác xung quanh hệ thống tập tin của tôi (tác dụng phụ của quá trình xây dựng) đặt một số biến môi trường toàn cầu (LD_LIBRARY_PATH, PATH, ROOTDIR, v.v.) cần phải nằm trong vỏ của tôi để hoạt động đúng. Tất nhiên, điều đó có nghĩa là tôi cần source script.shhoặc . script.shđể nó hoạt động, và không ./script.sh(điều này sẽ sinh ra một shell mới và không đặt các biến trong shell hiện tại của tôi).

Có bất cứ điều gì tôi có thể thêm vào tập lệnh để ngăn chặn (hoặc cảnh báo) ai đó đang chạy ./script.shkhông?

Câu trả lời:


15

Trong tập lệnh shell, $0là tên của tập lệnh hiện đang chạy. Bạn có thể sử dụng điều này để biết nếu bạn đang có nguồn gốc hoặc chạy như thế này:

if [[ "$(basename -- "$0")" == "script.sh" ]]; then
    echo "Don't run $0, source it" >&2
    exit 1
fi

5

Cách đơn giản nhất bashlà:

if [ "$0" = "$BASH_SOURCE" ]; then
    echo "Error: Script must be sourced"
    exit 1
fi

$BASH_SOURCE luôn chứa tên / đường dẫn của tập lệnh.

$0 chỉ chứa tên / đường dẫn của tập lệnh khi KHÔNG có nguồn gốc.

Vì vậy, khi chúng khớp, điều đó có nghĩa là kịch bản KHÔNG có nguồn gốc.


1

Điều này đã được thảo luận về SO . Các câu trả lời nhiều nhất upvoted bởi @barroyo nói đến việc sử dụng

[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "script ${BASH_SOURCE[0]} is being sourced ..."

@will: Hướng dẫn sử dụng cho biết: Một biến mảng có thành viên là tên tệp nguồn trong đó tên hàm shell tương ứng trong biến mảng FUNCNAME được xác định. Làm thế nào một chức năng?
serv-inc

1

Một tùy chọn khác có thể là loại bỏ quyền thực thi. Trong trường hợp đó, nó không thể được thực thi nhưng nó vẫn có thể có nguồn gốc.


1
Điều này là không đầy đủ. Bạn vẫn có thể chạy các tập lệnh bash scriptbất kể cờ thực thi trên tập lệnh. Cũng theo Cygwin (số này có tính không?) Bạn không thể lấy đi các cờ thực thi.
Tino

0

Ngoài ra, để kiểm tra $ 0 ( câu trả lời Mikel ) có thể hữu ích để thay đổi tiện ích mở rộng từ .sh sang .src chẳng hạn. Nó sẽ giúp hiểu bất cứ ai không nên thực hiện kịch bản này.


0

Tạo một trình thông dịch tùy chỉnh source_reminder:

#!/bin/sh
printf "%s\n" "Source me!" >&2
exit 1

Đừng quên làm cho nó thực thi được. Sau đó, chỉ cần sử dụng nó trong kịch bản của bạn:

#!/path/to/your/source_reminder
foo
bar
whatever

Bây giờ nếu bạn chạy tập lệnh mà không tìm nguồn cung ứng, lời nhắc sẽ thực hiện công việc của nó.


Bắt đẹp. #!/bin/echo do not executehoặc #!/bin/falsehoặc #!/usr/bin/awk BEGIN { print "you must source " ARGV[1]; exit(1) }. Tuy nhiên, điều này không bắt được trường hợp tập lệnh được thực thi với nội dung giống như sh script(vì điều này bỏ qua Shebang).
Tino
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.