pourquoi le code d'erreur 1 renvoyé en chargeant .bash_profile dans Mac

7

A chaque fois que j'ouvre un terminal bash, le code d'erreur 1 est renvoyé:

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

J'ai trouvé cela est causé par la dernière ligne de code dans mon .bash_profile:

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

Si je supprime cette ligne, le code d'erreur 0 est renvoyé. Je ne comprends pas comment cette ligne pourrait poser problème, car je peux me procurer .bash_profile avec le code d'erreur 0:

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

Mettre à jour:

Est-ce que quelqu'un sait comment Mac charge ~ / .bash_profile? Je doute que Mac l’utilise quand un shell de connexion est lancé. Il semble que le return commande ne fonctionne pas comme prévu - quand je mets return 5 comme la dernière ligne de ~/.bash_profile et lancez un shell de connexion, il ne renvoie pas le code d'erreur 5 (et je suis sûr ~/.bash_profile est le dernier script chargé).

RNA
la source
Mac OS X bash charge ses fichiers de points de la même manière que sur d’autres plates-formes (en gardant à l’esprit le terminal OS X, le shell de connexion démarre toujours dans un nouvel onglet ou une nouvelle fenêtre). La seule explication qui me vienne à l’esprit est qu’il existe bien un autre fichier chargé après .bash__profile, un dans lequel le exporté profile_bash_profile est utilisé et provoque une erreur (d'où le code de sortie 1 - peut-être parce que la variable var n'est pas définie sur chemin, mais uniquement sur un nom de fichier?).
kopischke
Quels sont les fichiers pouvant être chargés après .bash_profile? Je n'ai que ~ / .bashrc et je n'ai pas ~ / .profile, donc je ne pense pas avoir d'autres fichiers chargés après .bash_profile.
RNA
C’est difficile à dire sans accès à la configuration de votre système. Vérifier .bash_profile pour tout ce qui source d'autres fichiers (comme, par exemple, .bashrc ), puis tout ce qui est inclus par homebrew si vous utilisez ça.
kopischke

Réponses:

5

Notez que ce qui se passe quand on utilise return en dehors d'une fonction sans avoir source d le script (par exemple return provenant de .bash_profile ) est non documenté dans man bash.

La différence réside dans la façon dont le code de retour d’un script ou d’une fonction est enregistré en interne dans bash. Si vous return une valeur, cette valeur se voit attribuer le code retour du appel code, par exemple la fonction à partir de laquelle vous revenez, ou la source commander. Comme il n’existe aucun appelant de ce type au retour de .bash_profile lors de l'initialisation du shell, cette valeur est simplement ignorée. Qu'est-ce que vous accédez en tant que $? est le code retour de l'instruction précédente .

Utiliser Apple bash-86.1 comme référence:

Si vous source un script, son contenu est analysé et exécuté, jusqu'à ce qu'un return déclaration est rencontrée. Sa valeur de retour est enregistrée séparément et c’est la responsabilité de l’appelant ( execute_command_internal dans bash-3.2/execute_cmd.c ) pour attribuer sa valeur à la variable contenant le dernier code de sortie: last_command_exit_value.

S'il est appelé en tant que script de démarrage, il est chargé via un appel à maybe_execute_file dans le run_startup_files fonctionner dans bash/shell.c. L’exécution de la commande n’est pas régulière: le contenu du fichier est exécuté correctement, y compris le fichier final. return, personne ne se soucie de la valeur réelle de votre retour. Il est simplement jeté.

Alors, quel comportement voyez-vous ici ? Essentiellement les mêmes que si vous aviez appelé return sans argument: comme return renvoie simplement le code de retour de la commande qui la précède, qui dans votre cas est le test ayant échoué.

Comment obtenir le comportement souhaité? Puisque vous ne pouvez pas exit de .bash_profile sans quitter le shell, vous devez vous assurer que la commande qui le précède immédiatement produit le code de retour souhaité, dans ce cas:

test -f $HOME/.debug && export profile_bash_profile='.bash_profile' || { true; return; }
Daniel Beck
la source
Alors, que faire si je n'ai pas de test commandes dans mon .bashrc?
Iulian Onofrei
@IulianOnofrei Vous pouvez rencontrer le même problème avec un nombre quelconque de commandes en supposant que vous utilisez le même motif de return usage.
Daniel Beck
Je comprends. Donc ça marche si j'ai some_command \n true; return;?
Iulian Onofrei
@ IulianOnofrei Je suppose donc. Mais notez bien que cela fait presque quatre ans que j'ai fait des recherches et répondu à cette question.
Daniel Beck
Merci! Et, bien sûr, pas de problème, je vais creuser.
Iulian Onofrei
2

J'ai compris ce qui suit par essais et erreurs. Peut-être qu'un guru BASH peut en expliquer davantage.

  1. .bashrc Contenu:

    test -f $HOME/existent_file || return 4
    

    Après avoir ouvert un nouveau terminal:

    $ echo $?
    0
    
  2. .bashrc Contenu:

    test -f $HOME/non_existent_file || return 4
    

    Après avoir ouvert un nouveau terminal:

    $ echo $?
    1
    
  3. .bashrc Contenu:

    function foo () { 
        return 4 
    }
    foo;
    

    Après avoir ouvert un nouveau terminal:

    $ echo $?
    4
    
  4. .bashrc Contenu:

    return 4
    

    Après avoir ouvert un nouveau terminal:

    $ echo $?
    0
    
  5. Avec le même .bashrc comme ci-dessus:

    $ source ~/.bashrc
    $ echo $?
    4
    
  6. Ces commandes s’exécutent directement à partir d’un terminal:

    $ 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
    

Alors, return fonctionne uniquement à partir de fonctions et de fichiers sources. Je ne sais pas Comment un utilisateur ~/.bashrc est lu mais apparemment ce n’est pas une source.

terdon
la source
Bon travail de détective, conduisant à des résultats fascinants! Cela semble être l’illustration de la réponse de Daniel. BTW, il ne devrait pas question, mais sur quelle plate-forme étiez-vous? (Mac?)
Scott
@ Scott, merci :). Je suis sous Linux, Linux Mint Debian pour être précis et bash 4.2.36 (1).
terdon