Uruchom zsh z niestandardowym zshrc

17

Chcę móc uruchomić zsh z niestandardowym plikiem rc podobnym do polecenia: bash --rc-file /path/to/file

Jeśli nie jest to możliwe, to czy można uruchomić Zsh, uruchomić source /path/to/file, a następnie pozostać w tej samej sesji Zsh?

Uwaga: polecenie zsh --rcs /path/to/filenie działa, przynajmniej nie dla mnie ...

EDYCJA: W całości chcę móc wykonać następujące czynności: sshna zdalnym serwerze „przyklad.com”, uruchom zsh, sourcemoja konfiguracja znajduje się /path/to/filew poleceniu wszystko w 1. To właśnie tam walczyłem, szczególnie dlatego, że wolałbym nie zapisywać żadnych plików konfiguracyjnych na zdalnym komputerze.

hjkatz
źródło
1
Cześć Katz, witamy na unix.SE. Zredagowałem twoje pytanie, aby dodać formatowanie, które sprawia, że ​​(nieco) jest łatwiejszy do odczytania. Możesz kliknąć „edytuj”, aby zobaczyć, jak to działa. Usunąłem również kilka dodatkowych rzeczy, takich jak „Dziękuję” i twój podpis (wszystkie posty w sieci Stack Exchange są automatycznie podpisywane).
drs
1
Dziękuję, nauczyłem się teraz pisać code as such!
hjkatz

Odpowiedzi:

18

Ze stron podręcznika:

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.

więc powinieneś być w stanie ustawić zmienną środowiskową ZDOTDIRna nowy katalog, aby zsh szukał innego zestawu plików dot.

Jak sugeruje strona podręcznika, RCSi GLOBAL_RCSnie są ścieżkami do plików rc, gdy próbujesz ich użyć, ale raczej opcje, które możesz włączyć lub wyłączyć. Na przykład flaga --rcswłączy tę RCSopcję, powodując, że zsh będzie czytać z plików rc. Możesz użyć następujących flag wiersza poleceń, aby włączyć lub wyłączyć zsh RCSlub GLOBAL_RCS:

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

Aby odpowiedzieć na inne pytanie:

czy można uruchomić Zsh, uruchomić „source / path / to / file”, a następnie pozostać w tej samej sesji Zsh?

Tak, jest to dość łatwe zgodnie z powyższymi wskazówkami. Po prostu biegnij zsh -d -fi wtedy source /path/to/zshrc.

jayhendren
źródło
Ponieważ działa to na moje pytanie, nie wspomniałem, że mogę uruchomić tylko jedną komendę. To nie spełnia tego, do czego chcę tego używać (niestandardowy ssh z moimi osobistymi konfiguracjami). Problem polega na tym, że uruchomienie zsh -d -f; source /path/to/filenigdy nie wykonuje drugiego polecenia w pierwszej sesji zsh aż do wyjścia.
hjkatz
W całości chciałbym móc wykonać następujące czynności. sshna zdalny serwer „przyklad.com”, uruchom zsh, sourcemoja konfiguracja znajduje się pod /path/to/file, polecenie wszystko w 1. To właśnie tam walczyłem, szczególnie dlatego, że wolałbym nie zapisywać żadnych plików konfiguracyjnych na zdalnym komputerze. Dziękuję za odpowiedź!
hjkatz
wygląda na to, że twoim problemem nie jest używanie niestandardowego zshrc, ale brak wiedzy o tym, jak używać powłoki nad ssh. Jeśli uruchomisz ssh host "zsh -d -f; source /path/to/file", ssh uruchomi się najpierw zshna zdalnym hoście, a następnie source ...po wyjściu powłoki zsh. Zamiast tego chcesz ssh -t host zsh -d -fupuścić się w interaktywną powłokę na zdalnym hoście lub, jeśli nie chcesz interaktywnej powłoki, zrób to ssh host zsh -d -f -c \"source /path/to/file\; other command\; ... \".
jayhendren
Nie, rozumiem, jak ssh działa z interaktywnymi powłokami. Problem polega na tym, że bieganie ssh -t host "zsh -d -f; source /path/to/fileupuszcza mnie do interaktywnej (i jałowej) zshpowłoki.
hjkatz
1
Mówiłem już, dlaczego tak jest i jak to naprawić. Po uruchomieniu ssh -t host "zsh -d -f; source /path/to/file"polecenie source...NIE jest uruchamiane w powłoce zsh. Jest uruchamiany w powłoce logowania po wyjściu z powłoki zsh. Aby to przetestować, uruchom ssh host "zsh; echo foo". Zobaczysz wynik „foo” po wyjściu z powłoki zsh.
jayhendren
4

podczas gdy w ZDOTDIR możesz zshzinterpretować plik wywoływany .zshrcw dowolnym wybranym katalogu, interpretacja dowolnego pliku (niekoniecznie wywołanego .zshrc) okazuje się dość trudna.

W shlub kshemulacji, zshocenia $ENV; więc możesz dodać emulate zshu góry /path/to/filei zrobić:

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

Innym bardzo skomplikowanym podejściem może być:

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

Ten zasługuje na trochę wyjaśnienia.

${foo::=value}jest zmiennym rozszerzeniem, które faktycznie ustawia $foo . $functionsto specjalna tablica asocjacyjna, która odwzorowuje nazwy funkcji na ich definicje.

Dzięki tej promptsubstopcji zmienne w $PS1są rozszerzane. Tak więc po pierwszym pytaniu zmienne w tym PS1 zostaną rozwinięte.

Ta zsh_directory_namefunkcja jest funkcją specjalną, która pomaga rozwinąć ~foodo /path/to/somethingi do tyłu. Jest to używane na przykład %~w znaku zachęty, więc jeśli bieżącym katalogiem jest /opt/myproj/proj/x, możesz go wyświetlić tak jak ~proj:xpoprzez zsh_directory_namemapowanie proj:x<=> /opt/myproj/proj/x. Jest to również używane przez Dflagę rozszerzenia parametru. Więc jeśli ktoś się rozszerzy ${(D)somevar}, zsh_directory_namefunkcja ta zostanie wywołana.

Tutaj używamy ${(D):-}, ${:-}czyli ${no_var:-nothing}rozszerza się nothing, gdy $no_varjest pusty, więc ${(D):-}rozwija się niczym podczas wywoływania zsh_directory_name. zsh_directory_namezostał wcześniej zdefiniowany jako:

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

Oznacza to, że po pierwszym rozszerzeniu PS1 (po pierwszym pytaniu) ${(D):-}spowoduje wyłączenie promptsubstopcji (anulowanie -o promptsubst), zsh_directory_name()niezdefiniowanie (ponieważ chcemy uruchomić ją tylko raz) $PS1i /path/to/filewyłączenie.

${PS1=%m%# }rozwija się (i przypisuje $PS1) do, %m%#chyba że PS1 został już zdefiniowany (na przykład /path/to/filepo po unset) i %m%#zdarza się, że jest wartością domyślną PS1.

Stéphane Chazelas
źródło
Wygląda to dość ekstrawagancko i spróbuję jak najszybciej. Mam nadzieję, że to działa!
hjkatz