L'écran GNU n'héritera pas de mon PATH sur 10.5.8

11

J'utilise l'écran quotidiennement pour les besoins de mon terminal et j'en suis très satisfait. Récemment, cependant, je fait quelques mises à jour de mes fichiers de configuration de bash et j'ai remarqué que je mettais divers PATHéléments ( PATH, MANPATH, INFOPATH, etc.) en 2 endroits. J'ai modifié les fichiers pour qu'ils soient ce qu'ils devraient être et maintenant toutes mes variables d'environnement sont définies une fois .bash_profile. C'est là que réside mon problème.

Apparemment, la raison pour laquelle je les installais à deux endroits était à cause de l'écran. écran apparaît seulement exécuter .bashrcet ne pas semble hériter mes PATHou tout autre variables d' environnement correctement de mon shell bash d' origine. Parce qu'il s'exécute uniquement .bashrcet que je ne place maintenant que mes variables .bash_profile, j'obtiens un fichier incomplet PATH.

Ma question est alors de savoir comment obtenir mes variables d'environnement à l'écran sans la duplication. La lecture des Bashdocuments semble indiquer que ce pourrait être le type de shell que l'écran utilise pour se connecter, c'est-à-dire un shell interactif sans connexion, mais je ne pouvais pas comprendre comment forcer l'écran à utiliser un type de shell particulier, seul le shell à utiliser via -s /bin/bash.

Vous pouvez parcourir mes fichiers de configuration sur ma page GitHub . C'est le commit commit qui a cassé l'écran .

EDIT: J'utilise Screen version 4.00.03 (FAU) 23-Oct-06et j'ai tendance à l'invoquer enscreen -h 50000

EDIT: J'ai maintenant pu tester cela sur Cygwin ( CYGWIN_NT-5.1 1.7.1(0.218/5/3) i686, Screen version 4.00.03 (FAU) 23-Oct-06) et il présente un comportement différent de celui de mon Mac.

Le comportement spécifique que j'ai découvert est que, dans Cygwin, les modifications que PATHj'apporte dans .bash_profile sont dupliquées lors de l'entrée dans l'écran, puis la création successive de fenêtres d'écran ne duplique pas le chemin, mais re-source .bash_profile.

Pour illustrer le comportement dont je parle:

Sortie d'un nouveau terminal:

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

Sortie de la première invocation d'écran:

[~]$ screen -h 50000 -s -/bin/bash

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man:/home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man:/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

Appels ultérieurs à C-a c:

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man:/home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man:/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

Tu peux voir

Tim Visher
la source
La duplication est due au fait que bash est configuré pour ajouter inconditionnellement ces entrées, car il s'agit d'un shell de «connexion», et vous dites à l' écran d'appeler bash en tant que shell de «connexion». J'ai réécrit ma réponse pour essayer de résoudre les problèmes généraux des variables shell, écran et environnement.
Chris Johnsen

Réponses:

16

écran et variables d'environnement

Par défaut, screen transmet à ses shells (et autres processus) quelles que soient les variables d'environnement qu'il avait au démarrage de la session (c'est-à-dire que la reconnexion ne change pas quelles variables d'environnement sont données aux nouveaux shells). Mais parce que les fichiers de configuration d' écran et de shell changent généralement les variables d'environnement, il existe de nombreux endroits où des modifications inattendues peuvent être introduites. Il y a quelques variables, comme TERM , que l' écran change presque toujours, mais celles-ci sont généralement requises pour les fonctionnalités que l' écran fournit.

Disons que ni la configuration de votre shell, ni la configuration de l' écran ne modifiera une variable nommée FOOBAR (assez probablement, dans l'ensemble). Si vous démarrez une session avec FOOBAR=foo screen, tous les shells créés dans cette session auront une variable d'environnement nommée FOOBAR avec une valeur de foo.

Les choses deviennent plus compliquées pour les variables que l' écran ou votre shell peuvent modifier.

Paramètres manquants lors de l'utilisation de l' écran

Coquilles de connexion

Si vous constatez que certains paramètres sont manquants dans les shells démarrés par l' écran , c'est peut-être parce que votre shell est configuré uniquement pour mettre à jour ces paramètres pour les shells de «connexion». La plupart des shells comprennent une convention spéciale (en C:) **argv == '-'que l' écran peut être configuré pour utiliser.

Selon la documentation de l' écran :

commande shell

Définissez la commande à utiliser pour créer un nouveau shell. Cela remplace la valeur de la variable d'environnement $ SHELL. Ceci est utile si vous souhaitez exécuter un tty-enhancer qui s'attend à exécuter le programme spécifié dans $ SHELL. Si la commande commence par un caractère «-», le shell sera démarré en tant que login-shell.

Pour avoir des shells de démarrage d' écran en tant que shells de connexion, démarrez l' écran avec screen -s -/bin/bashou ajoutez cette ligne à votre .screenrc:

shell -/bin/bash

Ajustez le chemin vers le shell que vous utilisez.

configuration de l' écran

Les variables d'environnement manquantes ou réinitialisées peuvent également être dues à setenvet aux unsetenvcommandes d'un fichier de configuration d' écran . Vous devrez vérifier à la fois le .screenrc dans votre répertoire personnel et le fichier que votre compilation d' écran utilise comme 'system screenrc' (vous pouvez essayer une commande comme strings "$(which screen)" | fgrep -i screenrctrouver le chemin d'accès qui a été configuré au moment de la compilation - c'est généralement / etc / screenrc pour un écran installé par le système ; les installations complémentaires utiliseront probablement un autre nom de chemin). Vous pouvez utiliser SCREENRC=/dev/null SYSSCREENRC=/dev/null screenpour éviter temporairement ces fichiers de paramètres, mais il existe une option de compilation qui empêche l'utilisation efficace de SYSSCREENRC (probablement pour que les administrateurs système puissent forcer un peu de configuration initiale).

Paramètres en double lors de l'utilisation de l' écran

Il est assez courant d'ajouter des éléments à une variable d'environnement comme PATH dans les fichiers de configuration d'un shell afin que la valeur mise à jour soit disponible pour les sessions shell normales (par exemple xterm ou autres fenêtres de terminal, sessions de console, etc.). Si de tels éléments sont ajoutés dans la configuration par shell d'un shell (ou, si vous utilisez le -/path/to/shellparamètre décrit ci-dessus, dans la configuration par shell de connexion), le shell démarré par l' écran aura probablement plusieurs copies des éléments ajoutés.

Une stratégie pour éviter cela consiste à mettre tous les ajouts à des variables comme PATH dans la configuration par connexion de votre shell et à éviter d'utiliser le -/path/to/shellparamètre shell avec screen .

Une autre stratégie consiste à ajouter conditionnellement les nouveaux éléments à la variable. Selon le shell, le code pour ce faire peut être un peu compliqué, mais il peut généralement être encapsulé dans une fonction shell pour une utilisation facile.

Encore une autre stratégie consiste à toujours commencer avec une valeur fixe dans vos fichiers de configuration. Cela peut parfois provoquer des problèmes lors du déplacement de vos fichiers de configuration d'un système à un autre lorsque les valeurs par défaut peuvent varier considérablement.

Diagnostique

Si vous ne pouvez pas repérer directement où une modification particulière se produit, vous pouvez essayer ce qui suit pour localiser où le changement se produit.

Vérifiez la valeur actuelle dans votre shell initial:

echo "$PATH"

Vérifiez comment le shell lui-même modifie la valeur lors de la création d'un sous-shell:

/bin/bash -c 'echo "$PATH"'

Vérifiez comment le shell modifie la valeur lorsqu'un sous-shell de connexion est créé:

perl -e '$s=shift;exec {$s} "-$s", @ARGV or die "unable to start shell"' /bin/bash
echo "$PATH"
exit

Vérifiez comment l' écran modifie la valeur:

printf '#!/bin/sh\nl=/tmp/echo-var.log;rm -f "$l"; echo $PATH >"$l"' >/tmp/echo-var &&
chmod a+x /tmp/echo-var &&
screen -s /tmp/echo-var &&
cat /tmp/echo-var.log
Chris Johnsen
la source
Cela résout une partie de mon problème. Malheureusement, cela ne marche pas complètement. Maintenant, l'écran fonctionne correctement, screen -s -/bin/bashmais il ne se comporte pas car je m'attends à ce qu'il se comporte sous Cygwin sur ma machine de travail. Sur cette machine, je cours screen -h 50000et elle hérite simplement de mon PATHsans réellement réapprovisionner le fichier. Cela s'exécute à chaque fois que je lance une nouvelle fenêtre.
Tim Visher
L'environnement du processus d' écran doit toujours être hérité par tous ses enfants (sauf pour des choses comme TERM qu'il pourrait remplacer). Essayez de FOOBAR=baz screenvérifier echo $FOOBARles fenêtres shell à partir de screenet screen -s -/bin/bash. Les deux variantes devraient avoir FOOBAR= baz. Si votre PATHest en cours de modification, alors vous devrez retrouver ce qui le fait. Essayez SYSSCREENRC=/dev/null SCREENRC=/dev/null screen, si cela vous permet de PATHpasser, alors c'est probablement un setenv PATHin /etc/screenrcou ~/.screenrc. Sinon, c'est quelque chose que vous .bashrcfaites.
Chris Johnsen
J'ai fait une grande réécriture de / ajout à ma réponse.
Chris Johnsen
2

La dernière fois que j'ai vu un problème similaire, je l'ai résolu en utilisant screen -llors du démarrage de l'écran.

Vous pouvez utiliser l' -loption lors de l'appel screen(activer le mode de connexion ; également contrôlé par les commandes defloginet logindans .screenrc) pour définir si l'écran doit ouvrir la fenêtre par défaut (ajouter / supprimer l'entrée / etc / utmp).

Le mode de connexion est activé par défaut, mais il peut être modifié au moment de la compilation. Si screen n'est pas compilé avec le support utmp, ces commandes ne sont pas disponibles.

Je ne semble pas avoir besoin du -lmode dans l'écran par défaut de Debian Lenny (v4.0.3); il semble être activé par défaut. Mon ~/.profileet ~/.bashrcsont lus correctement. Comment invoquez-vous screen? Quelle version utilisez-vous?

Quack Quichotte
la source
tho sous cette théorie, nescreen -ln devrait pas exécuter mon ~/.profile, et il est toujours exécuté. essayez donc le -ldrapeau, mais ce n'est probablement pas la bonne réponse. le laissera ici pour le moment.
Quack Quichote
Il semble que -lseul contrôle si screenajoute une entrée au utmpfichier, pas s'il invoque de nouveaux shells avec leur propre -loption ou utilise la -coutume exec- with -prefix.
Chris Johnsen
2

Le problème réside dans le comportement de launchd sur Leopard. Consultez ce rapport de bogue MacPorts pour un écran sur Leopard pour voir pourquoi il ne sera jamais corrigé à moins que vous ne puissiez en quelque sorte rétroporter le lancement de Snow Leopard.

https://trac.macports.org/ticket/18235#comment:26

ClashTheBunny
la source
1

Il n'y a rien de mal à trouver votre .bashrc à partir de .bash_profile. Si vous n'utilisez votre machine que localement, votre .bash_profile ne sera dans la plupart des cas sourcé que lors de votre connexion initiale (il y a évidemment d'autres fois où il est sourcé).

J'organise mes fichiers de sorte que si je veux que quelque chose soit fait uniquement lorsque je me connecte, je mets les informations dans .bash_profile et pour tout le reste je les mets dans .bashrc. PATH est une chose que je mets dans mon .bashrc, et je source .bashrc dans mon .bash_profile.


la source
Seriez-vous à l'aise de publier vos fichiers .bashrcet .bash_profilequelque part afin que je puisse les voir? Le problème que j'ai rencontré en faisant quelque chose de similaire était que PATHcela augmenterait à chaque fois que je créerais une nouvelle instance d'écran car elle hériterait de l'ancienne PATHet ensuite ajouterait tout à nouveau.
Tim Visher
Désolé Tim, je n'ai pas vu ça ... J'ai changé beaucoup de choses autour de sorte qu'elles n'auront pas beaucoup de sens, mais c'est essentiellement ce que je fais. # .bash_profile if [-f ~ / .bashrc]; puis . ~ / .bashrc fi Ensuite, je mets tout le reste dans .bashrc, à l'exception des choses que je veux démarrer lors de ma première connexion, qui vont également dans .bash_profile. PATH est géré dans .bashrc comme une série de lignes au lieu d'une définition de chemin comme la plupart des exportations PATH = / chemin / vers / binaires1: $ PATH export PATH = / chemin / vers / binaires2: $ PATH
0

Chaque fois que j'ai un problème comme ça , je crée un fichier $HOME/.debuget dans tous les fichiers est notre source / exécuté lors de la connexion / appel shell (par exemple ~/.bashrc, ~/.bash_profile, ~/.profile, /etc/bashrc, etc.) J'ai la première ligne

test -f $HOME/.debug && echo $HOME/.bashrc 1>&2

ou similaire. Pour un débogage spécifique, vous pouvez également ajouter des éléments tels que

test -f $HOME/.debug && echo PATH now equals $PATH 1>&2

De cette façon, vous pouvez être sûr à 100% des fichiers utilisés ou non.

La redirection vers stderr est importante, vous ne voulez pas que quelque chose gâche stdout dans de nombreuses situations.

hlovdal
la source
0

Vous pouvez rester avec .profile car le système ne touche pas bashrc (comme la session graphique) Maintenant, vous avez simplement deux ensembles d'environnement différents - un à partir de .profile, l'autre pour bash à partir de .bashrc.

ZaB
la source