Démarrez zsh avec un zshrc personnalisé

17

Je veux pouvoir démarrer zsh avec un fichier rc personnalisé similaire à la commande: bash --rc-file /path/to/file

Si ce n'est pas possible, est-il possible de démarrer zsh, d'exécuter source /path/to/file, puis de rester dans la même session zsh?

Remarque: La commande zsh --rcs /path/to/filene fonctionne pas, du moins pas pour moi ...

EDIT: Dans son intégralité, je souhaite pouvoir faire ce qui suit: sshsur un serveur distant "example.com", exécutez zsh, sourcema configuration se trouvant sur /path/to/file, all in 1 command. C'est là que j'ai eu du mal, surtout parce que je préfère ne pas écraser les fichiers de configuration sur la machine distante.

hjkatz
la source
1
Salut Katz, bienvenue sur unix.SE. J'ai modifié votre question pour ajouter une mise en forme qui la rend (légèrement) plus facile à lire. Vous pouvez cliquer sur "modifier" pour voir comment cela fonctionne. J'ai également supprimé des éléments supplémentaires, comme "Merci" et votre signature (tous les messages sur le réseau Stack Exchange sont automatiquement signés).
drs
1
Merci, j'ai maintenant appris à taper code as such!
hjkatz

Réponses:

18

Depuis les pages de manuel:

STARTUP/SHUTDOWN FILES
       Commands are first read from /etc/zshenv; this cannot be overridden.  Subsequent  be‐
       haviour is modified by the RCS and GLOBAL_RCS options; the former affects all startup
       files, while the second only affects global startup files (those shown here  with  an
       path starting with a /).  If one of the options is unset at any point, any subsequent
       startup file(s) of the corresponding type will not be read.  It is also possible  for
       a  file  in  $ZDOTDIR  to  re-enable  GLOBAL_RCS.  Both RCS and GLOBAL_RCS are set by
       default.

       Commands are then read from $ZDOTDIR/.zshenv.  If the shell is a  login  shell,  com‐
       mands are read from /etc/zprofile and then $ZDOTDIR/.zprofile.  Then, if the shell is
       interactive, commands are read from /etc/zshrc and then $ZDOTDIR/.zshrc.  Finally, if
       the shell is a login shell, /etc/zlogin and $ZDOTDIR/.zlogin are read.

       When a login shell exits, the files $ZDOTDIR/.zlogout and then /etc/zlogout are read.
       This happens with either an explicit exit via the exit  or  logout  commands,  or  an
       implicit exit by reading end-of-file from the terminal.  However, if the shell termi‐
       nates due to exec'ing another process, the logout files are not read.  These are also
       affected  by  the  RCS and GLOBAL_RCS options.  Note also that the RCS option affects
       the saving of history files, i.e. if RCS is unset when the shell  exits,  no  history
       file will be saved.

       If  ZDOTDIR  is unset, HOME is used instead.  Files listed above as being in /etc may
       be in another directory, depending on the installation.

       As /etc/zshenv is run for all instances of zsh, it is important that it  be  kept  as
       small  as  possible.  In particular, it is a good idea to put code that does not need
       to be run for every single shell behind a test of the form `if [[  -o  rcs  ]];  then
       ...' so that it will not be executed when zsh is invoked with the `-f' option.

vous devriez donc être en mesure de définir la variable d'environnement ZDOTDIRdans un nouveau répertoire pour que zsh recherche un ensemble différent de fichiers dot.

Comme le suggère la page de manuel, RCSet GLOBAL_RCSne sont pas des chemins d'accès aux fichiers rc, car vous essayez de les utiliser, mais plutôt des options que vous pouvez activer ou désactiver. Ainsi, par exemple, l'indicateur --rcsactivera l' RCSoption, provoquant la lecture de zsh à partir des fichiers rc. Vous pouvez utiliser les drapeaux de ligne de commande suivants pour zsh pour activer ou désactiver RCSou GLOBAL_RCS:

  --globalrcs
  --rcs
  -d    equivalent to --no-globalrcs
  -f    equivalent to --no-rcs

Pour répondre à votre autre question:

est-il possible de démarrer zsh, d'exécuter "source / chemin / vers / fichier", puis de rester dans la même session zsh?

Oui, c'est assez facile selon les directions ci-dessus. Courez zsh -d -fet ensuite source /path/to/zshrc.

jayhendren
la source
Comme cela fonctionne selon ma question, j'ai omis de mentionner que je ne peux exécuter qu'une seule commande. Cela ne satisfait pas ce pour quoi je souhaite l'utiliser (un ssh personnalisé avec mes configurations personnelles). Le problème réside dans le fait que l'exécution zsh -d -f; source /path/to/filen'exécute jamais la deuxième commande dans la première session de zsh jusqu'à la fermeture.
hjkatz
Dans son intégralité, je souhaite pouvoir faire ce qui suit. sshsur un serveur distant "example.com", exécutez zsh, sourcema configuration se trouvant dans /path/to/file, commande tout en 1. C'est là que j'ai eu du mal, surtout parce que je préfère ne pas écraser les fichiers de configuration sur la machine distante. Merci pour votre réponse!
hjkatz
semble que votre problème n'est pas d'utiliser un zshrc personnalisé mais de ne pas savoir comment utiliser un shell sur ssh. Si vous exécutez ssh host "zsh -d -f; source /path/to/file", ssh s'exécutera d'abord zshsur l'hôte distant, puis source ...après la fermeture du shell zsh. Au lieu de cela, ce que vous voulez faire est ssh -t host zsh -d -fde déposer dans un shell interactif sur l'hôte distant, ou si vous ne voulez pas de shell interactif, faites-le ssh host zsh -d -f -c \"source /path/to/file\; other command\; ... \".
jayhendren
Non, je comprends comment ssh fonctionne avec les shells interactifs. Le problème est que l'exécution ssh -t host "zsh -d -f; source /path/to/fileme laisse tomber dans un zshshell interactif (et stérile) .
hjkatz
1
Je vous ai déjà expliqué pourquoi et comment y remédier. Lorsque vous exécutez ssh -t host "zsh -d -f; source /path/to/file", la commande source...n'est PAS exécutée à l'intérieur du shell zsh. Il est exécuté dans votre shell de connexion après la fermeture du shell zsh. Pour tester cela, exécutez ssh host "zsh; echo foo". Vous verrez la sortie "foo" après avoir quitté le shell zsh.
jayhendren
4

tandis qu'avec ZDOTDIR, vous pouvez dire zshd'interpréter un fichier appelé .zshrcdans n'importe quel répertoire de votre choix, le faire interpréter n'importe quel fichier de votre choix (pas nécessairement appelé .zshrc) s'avère assez difficile.

Dans shou kshémulation, zshévalue $ENV; afin que vous puissiez ajouter emulate zshen haut de votre page /path/to/fileet faire:

ssh -t host 'zsh -c "ARGV0=sh ENV=/path/to/file exec zsh"'

Une autre approche très compliquée pourrait être:

ssh -t host 'PS1='\''${${functions[zsh_directory_name]::="
    set +o promptsubst
    unset -f zsh_directory_name
    unset PS1
    . /path/to/file
 "}+}${(D):-}${PS1=%m%# }'\' exec zsh -o promptsubst -f

Celui-là mérite un peu d'explication.

${foo::=value}est une expansion variable qui définit réellement $foo. $functionsest un tableau associatif spécial qui mappe les noms de fonction à leurs définitions.

Avec l' promptsubstoption, les variables dans $PS1sont développées. Ainsi, à la première invite, les variables de cette PS1 seront développées.

La zsh_directory_namefonction est une fonction spéciale qui permet d'étendre le ~foovers /path/to/somethinget l'inverse. Cela est utilisé par exemple avec %~dans l'invite pour que si le répertoire courant est, /opt/myproj/proj/xvous pouvez l'afficher comme ~proj:xen faisant zsh_directory_namele mappage proj:x<=> /opt/myproj/proj/x. Cela est également utilisé par le Ddrapeau d'expansion des paramètres. Donc, si l'on se développe ${(D)somevar}, cette zsh_directory_namefonction sera appelée.

Ici, nous utilisons ${(D):-}, ${:-}qui est ${no_var:-nothing}étend de façon à s'est vide, donc par rien tout en appelant . a été précédemment défini comme:nothing$no_var${(D):-}zsh_directory_namezsh_directory_name

zsh_directory_name() {
  set +o promptsubst
  unset -f zsh_directory_name
  unset PS1; . /path/to/file
}

C'est-à-dire que lors de la première extension PS1 (à la première invite), ${(D):-}l' promptsubstoption sera désactivée (pour annuler la -o promptsubst), zsh_directory_name()indéfinie (car nous voulons l'exécuter une seule fois) $PS1pour ne pas être définie et /path/to/filepour être sourcée.

${PS1=%m%# }se développe (et affecte $PS1) à %m%#moins que PS1 n'ait déjà été défini (par exemple par /path/to/fileaprès le unset), et %m%#se trouve être la valeur par défaut de PS1.

Stéphane Chazelas
la source
Cela semble assez extravagant et je vais l'essayer dès que possible. J'espère que cela fonctionne!
hjkatz