7

Всякий раз, когда я открываю терминал bash, возвращается код ошибки 1:

Last login: Tue Jan 15 16:19:53 on ttys000
spam@moss:~ $ echo $?
1

Я обнаружил, что это вызвано последней строкой кода в моем .bash_profile:

test -f $HOME/.debug && export profile_bash_profile='.bash_profile' || return 0

Если я удалю эту строку, то возвращается код ошибки 0. Я не понимаю, как эта строка может вызвать какие-либо проблемы, потому что я могу получить .bash_profile с кодом ошибки 0:

spam@moss:~ $ source .bash_profile
spam@moss:~ $ echo $?
0

Обновить:

Кто-нибудь знает, как Mac загружает ~/.bash_profile? Я сомневаюсь, что Mac использует его при запуске оболочки входа. Кажется, что команда return не выполняется должным образом - когда я помещаю return 5 в качестве последней строки ~/.bash_profile и запускаю оболочку входа в систему, она не возвращает код ошибки 5 (и я уверен, что ~/.bash_profile - это последний загруженный скрипт).

2 ответа2

5

Обратите внимание, что то, что происходит при использовании return вне функции без source сценария d (например, return из .bash_profile), не документировано в man bash .

Разница в том, как код возврата скрипта или функции записывается внутри bash . Если вы return значение, этому значению присваивается код возврата вызывающего кода, например, вызов функции, из которой вы возвращаетесь, или source команда. Так как при возврате из .bash_profile во время инициализации оболочки такого вызывающего абонента нет, это значение просто отбрасывается. Что вы получаете как $? код возврата предыдущего оператора .

Используя Apple Bash-86.1 в качестве ссылки:

Если вы source сценарий, его содержимое анализируется и выполняется, пока оператор return не встречается. Его возвращаемое значение записывается отдельно, и вызывающая сторона (execute_command_internal в bash-3.2/execute_cmd.c) несет ответственность за присвоение своего значения переменной, содержащей последний код выхода: last_command_exit_value .

Если он вызывается как сценарий запуска, он загружается с помощью вызова maybe_execute_file в функции run_startup_files в bash/shell.c . Это не обычное выполнение команды: хотя содержимое файла выполняется должным образом, включая окончательный return , никому нет дела до фактического значения, которое вы возвращаете. Это просто отбрасывается.

Итак, какое поведение вы видите здесь? По сути, так же, как если бы вы вызывали return без аргументов: Like return просто возвращал код возврата предшествующей ему команды, которая, в вашем случае, является неудачным тестом.

Как получить желаемое поведение? Поскольку вы не можете exit из .bash_profile без выхода из оболочки, вам нужно убедиться, что команда, непосредственно предшествующая ей, выдает желаемый код возврата, в этом случае:

test -f $HOME/.debug && export profile_bash_profile='.bash_profile' || { true; return; }
2

Я понял следующее методом проб и ошибок. Может быть, гуру BASH может объяснить еще немного.

  1. Содержание .bashrc :

    test -f $HOME/existent_file || return 4
    

    После открытия нового терминала:

    $ echo $?
    0
    
  2. Содержание .bashrc :

    test -f $HOME/non_existent_file || return 4
    

    После открытия нового терминала:

    $ echo $?
    1
    
  3. Содержание .bashrc :

    function foo () { 
        return 4 
    }
    foo;
    

    После открытия нового терминала:

    $ echo $?
    4
    
  4. Содержание .bashrc :

    return 4
    

    После открытия нового терминала:

    $ echo $?
    0
    
  5. С тем же .bashrc как указано выше:

    $ source ~/.bashrc
    $ echo $?
    4
    
  6. Эти команды запускаются непосредственно из терминала:

    $ test -f $HOME/existent_file  || return 4
    $ echo $?
    0
    $ test -f $HOME/non_existent_file  || return 4
    bash: return: can only `return' from a function or sourced script
    $ echo $?
    1
    

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .