Запустите zsh с пользовательским zshrc

17

Я хочу иметь возможность запустить Zsh с пользовательским файлом RC похож на команду: bash --rc-file /path/to/file

Если это невозможно, то возможно ли запустить zsh, запустить source /path/to/fileи остаться в том же сеансе zsh?

Примечание: команда zsh --rcs /path/to/fileне работает, по крайней мере, не для меня ...

РЕДАКТИРОВАТЬ: В целом я хотел бы иметь возможность сделать следующее: sshна удаленном сервере "example.com", запустить zsh, sourceмоя конфигурация находится в /path/to/file, все в 1 команду. Вот где я боролся, особенно потому, что я бы предпочел не записывать поверх файлов конфигурации на удаленной машине.

hjkatz
источник
1
Привет, Кац, добро пожаловать в unix.SE. Я отредактировал ваш вопрос, добавив немного форматирования, которое облегчает его чтение. Вы можете нажать «изменить», чтобы увидеть, как это работает. Я также удалил некоторые дополнительные элементы, такие как «Спасибо» и ваша подпись (все сообщения в сети Stack Exchange автоматически подписываются).
DRS
1
Спасибо, теперь я научился печатать code as such!
hjkatz

Ответы:

18

Из справочных страниц:

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.

поэтому вы должны иметь возможность установить переменную окружения ZDOTDIRв новый каталог, чтобы zsh искал другой набор файлов точек.

Как страница людей предполагает, RCSа GLOBAL_RCSне пути к радиоуправляемым файлам, как вы пытаетесь использовать их, а опцию вы можете включить или отключить. Так, например, флаг --rcsактивирует RCSопцию, заставляя zsh читать из rc-файлов. Вы можете использовать следующие флаги командной строки для zsh, чтобы включить или отключить RCSили GLOBAL_RCS:

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

Чтобы ответить на ваш другой вопрос:

Можно ли запустить zsh, запустить «source / path / to / file», а затем остаться в том же сеансе zsh?

Да, это довольно легко в соответствии с указанными выше инструкциями. Просто беги zsh -d -fи тогда source /path/to/zshrc.

jayhendren
источник
Так как это работает для моего вопроса, я не упомянул, что могу запустить только 1 команду. Это не удовлетворяет тому, для чего я хочу использовать это (пользовательский ssh ​​с моими личными конфигурациями). Проблема заключается в том, что при запуске zsh -d -f; source /path/to/fileне выполняется вторая команда в первом сеансе zsh до выхода.
hjkatz
В целом я хотел бы иметь возможность сделать следующее. sshна удаленный сервер "example.com", запустите zsh, sourceмоя конфигурация находится в /path/to/file, все в 1 команду. Вот где я боролся, особенно потому, что я бы предпочел не записывать поверх файлов конфигурации на удаленной машине. Спасибо за ответ, хотя!
hjkatz
Похоже, ваша проблема не в том, чтобы использовать пользовательский zshrc, а в том, чтобы не знать, как использовать оболочку поверх ssh. Если вы запустите ssh host "zsh -d -f; source /path/to/file", тогда ssh будет запускаться сначала zshна удаленном хосте, а затем source ...после выхода из оболочки zsh. Вместо этого вам нужно ssh -t host zsh -d -fзайти в интерактивную оболочку на удаленном хосте или, если вам не нужна интерактивная оболочка, сделать это ssh host zsh -d -f -c \"source /path/to/file\; other command\; ... \".
Джейхендрен
Нет, я понимаю, как ssh работает с интерактивными оболочками. Проблема в том, что при запуске ssh -t host "zsh -d -f; source /path/to/fileменя бросает в интерактивную (и бесплодную) zshоболочку.
hjkatz
1
Я уже говорил вам, почему это так и как это исправить. Когда вы запускаете ssh -t host "zsh -d -f; source /path/to/file", команда source...НЕ запускается внутри оболочки zsh. Он запускается в вашей оболочке входа в систему после выхода из оболочки zsh. Чтобы проверить это, запустите ssh host "zsh; echo foo". Вы увидите вывод «foo» после выхода из оболочки zsh.
Джейхендрен
4

в то время как с ZDOTDIR, вы можете сказать, zshинтерпретировать файл с именем.zshrc в любом каталоге по вашему выбору, а интерпретировать любой файл по вашему выбору (не обязательно вызываемый .zshrc) оказывается довольно сложно.

В shили kshэмуляция, zshоценивает $ENV; так что вы можете добавить emulate zshв верхней части /path/to/fileи сделать:

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

Еще один очень запутанный подход может быть:

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

Это заслуживает небольшого объяснения.

${foo::=value}это расширение переменной, которое на самом деле устанавливает $foo . $functionsэто специальный ассоциативный массив, который отображает имена функций в их определения.

С promptsubstопцией, переменные в $PS1раскрываются. Таким образом, при первом запросе переменные в этом PS1 будут расширены.

Эта zsh_directory_nameфункция представляет собой специальную функцию, которая помогает расширить ~fooдо /path/to/somethingи наоборот. Это используется, например, %~в приглашении, чтобы, если текущий каталог был, /opt/myproj/proj/xвы могли отобразить его ~proj:x, выполнив zsh_directory_nameсопоставление proj:x<=> /opt/myproj/proj/x. Это также используется Dфлагом расширения параметра. Так что, если кто-то расширяется${(D)somevar} , эта zsh_directory_nameфункция будет вызвана.

Здесь мы используем ${(D):-}, ${:-}то есть, ${no_var:-nothing}расширяется до nothingif $no_varпусто, поэтому ${(D):-}расширяется до нуля во время вызова zsh_directory_name. zsh_directory_nameранее был определен как:

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

То есть, на первое расширение PS1 (на первой строке), ${(D):-}приведет к тому , promptsubstвозможность быть снята с охраны (отменить -o promptsubst), zsh_directory_name()чтобы быть неопределенным (как мы хотим , чтобы запустить его только один раз) , $PS1чтобы быть снята с охраны, а также /path/to/fileбыть получены.

${PS1=%m%# }расширяется (и присваивается $PS1) до тех %m%#пор, пока PS1 уже не был определен (например, /path/to/fileпосле после unset), и %m%#оказывается значением по умолчанию PS1.

Стефан Шазелас
источник
Это выглядит довольно экстравагантно, и я попробую как можно скорее. Я надеюсь, что это работает!
hjkatz