Bash: виявити виконувати vs source у сценарії?


19

У мене є сценарій, який засмічений навколо моєї файлової системи (побічний ефект процесу збирання), який встановлює деякі змінні глобального середовища (LD_LIBRARY_PATH, PATH, ROOTDIR тощо), які повинні бути в моїй оболонці для правильної роботи. Звичайно, це означає, що мені потрібно source script.shабо . script.shзмусити його працювати, а не ./script.sh(який би породив нову оболонку і не встановив змінні в моїй поточній оболонці).

Чи можна щось додати до сценарію, щоб запобігти (або попередити) когось запуску ./script.sh?

Відповіді:


15

У скрипті оболонки $0- назва поточно запущеного сценарію. Ви можете скористатися цим, щоб сказати, чи є у вас джерело чи біг так:

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

5

Найпростіший спосіб bash- це:

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

$BASH_SOURCE завжди містить ім'я / шлях сценарію.

$0 містить лише ім'я / шлях сценарію, коли НЕ розміщено.

Тож коли вони співпадають, це означає, що сценарій НЕ був розміщений.


1

Про це йшлося в СО . Відповідь @barroyo, що найбільше підтримує, говорить про використання

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

@will: Посібник говорить: Змінна масиву, членами якої є вихідні назви файлів, де визначені відповідні назви функцій оболонки в змінній масиву FUNCNAME. Як функція?
серв-інк

1

Іншим варіантом може бути видалення дозволів на виконання. У такому випадку його неможливо виконати, але його все одно можна отримати.


1
Це неповно. Ви все ще можете запускати сценарії, bash scriptнезалежно від прапора для виконання сценарію. Також під Cygwin (чи вважається це?) Ви не можете зняти прапори, що виконуються.
Тіно

0

На додаток до перевірки $ 0 ( відповідь Мікеля ) може бути корисним, наприклад, для зміни розширення з .sh на .src. Це допоможе зрозуміти всіх, хто не повинен виконувати цей сценарій.


0

Створіть спеціальний перекладач source_reminder:

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

Не забудьте зробити його виконуваним. Тоді просто використовуйте його у своєму сценарії:

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

Тепер, якщо запустити сценарій без пошуку джерела, нагадування зробить свою роботу.


Гарний улов. #!/bin/echo do not executeабо #!/bin/falseабо #!/usr/bin/awk BEGIN { print "you must source " ARGV[1]; exit(1) }. Однак це не сприймає випадок, коли сценарій виконується щось подібне sh script(оскільки це ігнорує Шебанг).
Тіно
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.