Отключить функции / псевдонимы в исходном скрипте

#bash #function #alias

#bash #функция #псевдоним

Вопрос:

Я знаю, что могу запустить «оригинальную» команду (не псевдоним), используя либо или "" :

 ls
"ls"
  

Однако это не работает для функций. Также это требует, чтобы я каждый раз использовал этот синтаксис.

Возможно ли в исходном скрипте отключить все функции / псевдонимы из родительского процесса (того, который запускает мой скрипт)? Т.е. Если у пользователя в их терминале определены некоторые функции псевдонимов, я хочу, чтобы они были отключены в моем скрипте (но, конечно, я все еще хочу иметь возможность определять и использоватьсобственные псевдонимы / функции).

Комментарии:

1. Псевдонимы и функции из родительского процесса не должны иметь никакого эффекта в вашем сценарии, если вы не экспортируете функции или не создаете исходный сценарий.

2. Вы правы, я забыл упомянуть, что это исходный скрипт, мой плохой. Я отредактировал вопрос.

3. Вы могли бы префиксить все с builtin помощью или command (см. help builtin И help command ), но я знаю, что я не могу придумать способ сделать это автоматически в исходном скрипте без изменения «родительской» среды или потери преимуществ исходного скрипта.

4. Разумное решение, вероятно, заключается в том, чтобы не использовать исходный код вашего скрипта, а вместо этого заставить его печатать что-то, чему вызывающий должен доверять и eval .

5. @Socowi Сделайте свой комментарий ответом — если никто не придумает ничего лучшего, я приму это. Также, пожалуйста, объясните разницу между builtin и command в этом случае, если это возможно.

Ответ №1:

Типы команд в Bash

Bash знает разные типы команд, которые могут затенять друг друга. Приоритет этих типов:

  • Псевдонимы
    может быть определен пользователем с помощью alias cmd=...
  • функции
    может быть определен пользователем с помощью cmd() { ... }
  • встроенные
    непосредственно реализуются в bash и не могут быть изменены. help и enable перечислите все встроенные модули.
  • Исполняемые файлы в $PATH

Это означает, что если вы вводите cmd arg1 arg2 ... , вы используете псевдоним cmd , если он определен, в противном случае вы используете функцию cmd , если она определена, в противном случае вы используете встроенный cmd , если он встроенный, в противном случае вы используете первый исполняемый cmd файл из каталогов, $PATH если он есть, в противном случае вы получите ошибку -bash: cmd command not found .

Какой из этих случаев применяется cmd , можно проверить с помощью type -a cmd .

Управление приоритетом вручную

Bash позволяет вам определять, какой тип выбрать, используя кавычки и встроенные command функции и builtin .

  • cmd
    подавляет псевдонимы
    , использует функции, встроенные модули, исполняемые файлы
  • command cmd
    подавляет псевдонимы и функции
    , использует встроенные и исполняемые файлы
  • builtin cmd
    подавляет псевдонимы, функции и исполняемые
    файлы, использует только встроенные
  • enable -n cmd
    полностью отключает встроенное cmd , так что впоследствии используются только
    псевдонимы, функции и исполняемые файлы
  • env cmd
    не встроенный bash, поэтому он на самом деле ничего не подавляет, а
    использует только исполняемые файлы

Примеры

Затенение совершенно нормально. Например, bash имеет свой собственный встроенный echo , но ваша система также имеет /bin/echo . Обе реализации могут отличаться. Например, мой echo из bash 5 поддерживает uXXXX , а мой echo из GNU coreutils 8.3 — нет. Возможность таких различий становится еще более очевидной, если вы добавляете свои собственные реализации, используя псевдонимы и функции. Вот пример интерактивного сеанса bash ( $ это подсказка):

 $ echo() { printf "function echo: %sn" "$*"; }
$ alias echo='printf "alias echo: %s %s %sn"'
$ type -a echo
echo is aliased to `printf "alias echo: %s %s %sn"'
echo is a function
echo ()
{
    printf "function echo: %sn" "$*"
}
echo is a shell builtin
echo is /bin/echo

$ echo -e 'u2261'
alias echo: -e u2261
$ echo -e 'u2261'
function echo: -e u2261
# use the built-in (or executable file if there was no such built-in)
$ command echo -e 'u2261'
≡
$ builtin echo -e 'u2261'
≡

# use the executable /bin/echo
$ env echo -e 'u2261'
u2261

$ enable -n echo
# use the executable /bin/echo (`command` is needed to skip the alias and function)
$ command echo -e 'u2261'
u2261
  

Отвечая на ваш вопрос

К сожалению, я не знаю о чем-то вроде enable постоянного отключения поиска псевдонимов и функций. Вы могли бы попробовать некоторые хаки, такие как резервное копирование всех псевдонимов и функций, выполнение unset -f и unalias для них и восстановление их в конце. Однако unset может произойти сбой для функций только для чтения. Лучшим способом было бы использовать bash -c '... functions and aliases have no effect here ...' для тех частей, где вам действительно не нужны преимущества source . Для других частей префикс все с command .

Пожалуйста, обратите внимание: вызывающий абонент, который создает ваш скрипт, может даже отключить или затенить command , builtin , и так далее — поэтому вы никогда не можете быть уверены, что на самом деле используете ожидаемые команды. Даже запись /usr/bin/env executable или /path/to/the/executable не помогает, поскольку функция может иметь имя, и $PATH / или файловая система может быть изменена. Однако это не должно вас беспокоить. Тот, кто создает ваш скрипт, должен нести ответственность за обеспечение правильной среды.

Комментарии:

1. Отличный ответ! Однако в документации POSIX env говорится, что , если аргумент to env является встроенным, результаты не определены. Поэтому может быть неверно говорить env «использует только исполняемые файлы».

2. Спасибо, какая странная маленькая деталь. Я оставляю это из этого ответа, чтобы упростить его. Но благодаря вашему комментарию информация доступна для всех.

Ответ №2:

Редактировать: этот ответ может больше не иметь значения, поскольку вы отредактировали вопрос, чтобы уточнить, что сценарий является исходным кодом, а не выполняется в подоболочке.


Это происходит по умолчанию. Доказательство:

 $ function x() { echo 'hi'; }
$ x
hi
$ bash
# We are now in a subshell.
$ x
bash: x: command not found
  

Функции часто определяются в одном из файлов запуска оболочки: .bashrc , .profile или .bash_profile . Какие из них являются исходными, зависит от того, является ли оболочка оболочкой входа и / или интерактивной оболочкой. Оболочка, которая вызывается для выполнения сценария оболочки, не является ни оболочкой входа, ни интерактивной оболочкой, и в этом случае ни один из этих файлов не является исходным кодом.

Ответ №3:

РЕДАКТИРОВАТЬ: я должен прочитать более внимательно, поскольку вы не хотите создавать исходный сценарий, но должны быть получены, следующее для обратного пути:

Функции

Если вы исходите из своего родительского скрипта в начале, вы можете просто перебирать определенные функции и отменять их.

declare -F будут перечислены все определенные функции, но в формате declare -f functioname , поэтому вам нужно получить только имя:

 IFS=$'n'
for f in $(declare -F|cut -d ' ' -f 3); do
    unset -f $f
done
  

Псевдонимы

Псевдоним не должен быть указан, насколько я помню, но если они есть, вы можете сделать

 unalias -a
  

чтобы отменить их все.