Источник Bash — выбирает правильную функцию, когда два полученных файла имеют то же имя функции?

Я предлагаю, чтобы Вы изменили дом пользователя для указания на целевой каталог. Можно сделать это путем редактирования /etc/passwd непосредственно или usermod --home NEW_HOME_DIR username (это также скопирует файлы с предыдущего).

Обновление: Что касается блокировки, нет многих вариантов кроме a chroot тюрьма. Если Вы устанавливаете оболочку входа в систему на /bin/rbash, это запустит ограниченную оболочку. Среди прочего это означает cd не будет работать, ни будут команды то использование полные пути. Читайте bash(1) страница справочника под RESTRICTED SHELL для получения дальнейшей информации.

2
03.08.2013, 03:03
4 ответа

Можно отметить функцию как 'только для чтения' в file2.sh.

Примечание: это вызовет предупреждения, когда file1.sh более поздние попытки определить (переопределят) функцию.

Те предупреждения появятся на stderr и могли доставить неприятности. Я не знаю, могут ли они быть отключены.

Дальнейшее примечание: это МОГЛО БЫ заставить сценарии перестать работать, если они проверяют статус возврата функционального определения. Я думаю, что существует также опция удара, которая может быть установлена, который заставил бы ненулевой статус возврата где угодно прерывать выполнение сценария.Удачи!

Можно ли изменить file1.sh? Просто использование условных выражений, чтобы проверить, определяется ли функция прежде, чем определить его, было бы большим надежным решением.

Вот пример использования 'только для чтения'.

hobbes@metalbaby:~/scratch$ mkdir bash-source-test
hobbes@metalbaby:~/scratch$ cd bash-source-test
hobbes@metalbaby:~/scratch/bash-source-test$ cat > file2.sh
#!/bin/bash
fname(){
  echo "file2"
}

readonly -f fname
hobbes@metalbaby:~/scratch/bash-source-test$ cat > file1.sh
#!/bin/bash
fname(){
  echo "file1"
}

readonly -f fname
hobbes@metalbaby:~/scratch/bash-source-test$ cat >top.sh
#!/bin/bash 
if [ $1 ]; then
source file2.sh
fi  
source file1.sh

fname
hobbes@metalbaby:~/scratch/bash-source-test$ chmod +x *.sh
hobbes@metalbaby:~/scratch/bash-source-test$ ./top.sh 
file1
hobbes@metalbaby:~/scratch/bash-source-test$ ./top.sh hello
file1.sh: line 4: fname: readonly function
file2
hobbes@metalbaby:~/scratch/bash-source-test$ 
4
27.01.2020, 21:55
  • 1
    оба из Ваших предложений очень полезен. Я буду экспериментировать с ними обоими. –  MountainX-for-Monica 03.08.2013, 04:36
  • 2
    можно ли дать пример использования условных выражений, чтобы проверить, определяется ли функция прежде, чем определить его? Я хотел бы попробовать тот подход. (Я буду также гуглить вокруг и видеть, нахожу ли я пример.) –  MountainX-for-Monica 03.08.2013, 04:38
  • 3
    @MountainX, см. stackoverflow.com/questions/85880 / … для различных методов для определения, если имя существует как функция. –  daveloyall 12.08.2013, 17:45
  • 4
    недавнее редактирование удалил предупреждающее сообщение удара относительно попытки изменить функцию только для чтения. Я откатывал редактирование, потому что цель моего ответа состоит в том, чтобы продемонстрировать механику функций только для чтения. –  daveloyall 15.01.2015, 20:57

Если те сценарии действительно интерпретируются bash (а не в sh режим эмуляции), и если file1.sh определяет, но не использует foo, Вы могли переопределить source и . команды таким способом это после определения источника file1.sh, это удостоверяется file1.sh не переопределяет foo, например, путем искажения его далеко к чему-то еще:

$ cat file1.sh
foo() { echo original foo; }
$ cat file2.sh
foo() { echo new foo; }
$ cat main.sh
file2_sourced=false
source() {
  case ${1##*/} in
    (file2.sh)
      file2_sourced=true;;
    (file1.sh)
      if "$file2_sourced"; then
        alias foo=original_foo

        builtin source "$@"; local "ret=$?"
        unalias foo
        return "$ret"
      fi;;
  esac
  builtin source "$@"
}
.() { source "$@"; }

source file2.sh
source file1.sh

foo
original_foo

$ bash main.sh
new foo
original foo

Или возможно более соответствующий:

source() {
  shopt -s expand_aliases
  if [ "${1##*/}" = file1.sh ] && command -v foo > /dev/null 2>&1; then
    # foo already defined, make file1.sh define original_foo this time
    alias foo=original_foo
    builtin source "$@"; local "ret=$?"
    unalias foo
    return "$ret"
  else
    builtin source "$@"
  fi
}

Это: только предотвратите file1.sh от переопределения foo.

Теперь, если те другие сценарии это main.sh вызовы выполняются в противоположность тому, чтобы быть полученным, необходимо было бы экспортировать их source и . функции в main.sh:

export -f source .

На самом деле также возможно сделать это без изменения main.sh, путем вызова его как:

env BASHOPTS=expand_aliases source='() {
  if [ "${1##*/}" = file1.sh ] && command -v foo > /dev/null 2>&1; then
    # foo already defined, make file1.sh define original_foo this time
    alias foo=original_foo
    builtin source "$@"; local "ret=$?"
    unalias foo
    return "$ret"
  else
    builtin source "$@"
  fi
}' .='() { source "$@"; }' bash main.sh
1
27.01.2020, 21:55
  • 1
    Просто не получает файлы в порядке как в моем ответе достаточно? У меня есть подлое подозрение, что это не, и начиная с Вы и начиная с @daveloyall выбрали намного более сложные маршруты. –  terdon♦ 03.08.2013, 18:34
  • 2
    @terdon, мое понимание было то, что OP не имел никакого контроля на порядке file1.sh и file2.sh были получены и они могли быть получены несколько время из сценариев, которые он не мог изменить (почему мы не знаем). –  Stéphane Chazelas 03.08.2013, 20:13

Я ничего никогда не писал кроме маленьких сценариев удара для основного системного администратора и задач автоматизации, таким образом, у меня есть очень мало опыта с определением источника функций из других файлов. Это может поэтому быть очень наивно или не портативно или что-то, но, по крайней мере, в моей системе, и на большинстве языков программирования я знаю, если Вы переопределяете что-то, что это остается переопределенным.

Другими словами, пока Вы удостоверяетесь Вы источник file1.sh прежде file2.sh и экспортируйте функцию впоследствии, необходимо всегда экспортировать функцию из file2.sh если это было загружено и из file1.sh если это не имеет:

$ cat file1.sh 
#!/bin/bash
fname(){
  echo "BBBBB"
}

$ cat file2.sh 
#!/bin/bash
fname(){
  echo "CCCCC"
}

$ cat foobar.sh 
#!/bin/bash
source file1.sh
if [ $1 ]; then 
    source file2.sh;
fi
export -f fname;
./run_function.sh

$ cat run_function.sh 
#!/bin/bash
fname

Любые сценарии называют (например, ./run_function.sh) будет иметь какой бы ни fname был определен в последний раз, таким образом, они загрузят тот из file2.sh если это было получено и от file.sh если это не имеет:

$ ./foobar.sh
BBBBB
$ ./foobar.sh hello
CCCCC
1
27.01.2020, 21:55

Я думаю, что, вероятно, самый простой ответ здесь - получить функцию из этих файлов сценариев.

#file[12]
#foo() { : removed; }
. ./foo.fn
#and rest of script

#foo.fn
foo() { : old version is always defined; }
[ -z "${NEWFOO:+1}" ] ||
foo() { : new version defined only if $NEWFOO; }

#your caller script
export NEWFOO=1
case $srcarg in (./file1) unset NEWFOO;; esac
#or however ^that part^ is usually done
. "$srcarg"
#and rest of script
0
27.01.2020, 21:55

Теги

Похожие вопросы