Bash: mendeteksi eksekusi vs sumber dalam skrip?


18

Saya memiliki skrip yang berserakan di sistem file saya (efek samping dari proses build) yang menetapkan beberapa variabel lingkungan global (LD_LIBRARY_PATH, PATH, ROOTDIR, dll.) Yang perlu ada di shell saya untuk operasi yang tepat. Tentu saja, itu berarti saya perlu source script.shatau . script.shuntuk membuatnya bekerja, dan tidak ./script.sh(yang akan menelurkan shell baru dan tidak mengatur variabel di shell saya saat ini).

Adakah yang bisa saya tambahkan ke skrip untuk mencegah (atau memperingatkan) seseorang yang sedang menjalankan ./script.sh?

Jawaban:


14

Dalam skrip shell, $0adalah nama skrip yang sedang berjalan. Anda dapat menggunakan ini untuk mengetahui apakah Anda berasal atau dijalankan seperti ini:

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

4

Cara termudah bashadalah:

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

$BASH_SOURCE selalu berisi nama / jalur skrip.

$0 hanya berisi nama / jalur skrip ketika TIDAK bersumber.

Jadi ketika mereka cocok, itu berarti skrip TIDAK bersumber.


1

Ini telah dibahas pada SO . Jawaban yang paling banyak dipilih oleh @barroyo mengatakan untuk digunakan

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

@will: Manual mengatakan: Sebuah variabel array yang anggotanya adalah nama file sumber di mana nama fungsi shell yang sesuai dalam variabel array FUNCNAME didefinisikan. Bagaimana fungsinya?
serv-inc

1

Pilihan lain mungkin untuk menghapus izin eksekusi. Dalam hal ini tidak dapat dieksekusi tetapi masih dapat bersumber.


Ini tidak lengkap. Anda masih dapat menjalankan skrip dengan bash scriptterlepas dari tanda eksekusi pada skrip. Juga di bawah Cygwin (apakah ini diperhitungkan?) Anda tidak dapat menghapus flag yang dijalankan.
Tino

0

Selain memeriksa $ 0 ( jawaban Mikel ) mungkin berguna untuk mengubah ekstensi dari .sh ke .src, misalnya. Ini akan membantu untuk memahami siapa pun yang tidak boleh menjalankan skrip ini.


0

Buat juru bahasa khusus source_reminder:

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

Jangan lupa untuk membuatnya dieksekusi. Kemudian gunakan saja dalam skrip Anda:

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

Sekarang jika Anda menjalankan skrip tanpa sumber, pengingat akan melakukan tugasnya.


Tangkapan bagus. #!/bin/echo do not executeatau #!/bin/falseatau #!/usr/bin/awk BEGIN { print "you must source " ARGV[1]; exit(1) }. Namun ini tidak menangkap kasus di mana skrip dieksekusi dengan sesuatu seperti sh script(karena ini mengabaikan Shebang).
Tino
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.