Bắt đầu zsh với một zshrc tùy chỉnh


16

Tôi muốn có thể bắt đầu zsh với một tệp RC tùy chỉnh tương tự như lệnh: bash --rc-file /path/to/file

Nếu điều này là không thể, thì có thể bắt đầu zsh, chạy source /path/to/file, sau đó ở trong cùng một phiên zsh không?

Lưu ý: Lệnh zsh --rcs /path/to/filekhông hoạt động, ít nhất là đối với tôi ...

EDIT: Toàn bộ tôi muốn có thể làm như sau: sshđến một máy chủ từ xa "example.com", chạy zsh, sourcecấu hình của tôi nằm ở /path/to/file, tất cả trong 1 lệnh. Đây là nơi tôi đã vật lộn, đặc biệt là vì tôi không muốn ghi lại bất kỳ tệp cấu hình nào trên máy từ xa.


1
Xin chào Katz, chào mừng bạn đến với unix.SE. Tôi đã chỉnh sửa câu hỏi của bạn để thêm một số định dạng giúp dễ đọc hơn một chút. Bạn có thể nhấp vào "chỉnh sửa" để xem nó hoạt động như thế nào. Tôi cũng đã xóa một số thứ bổ sung, như "Cảm ơn" và chữ ký của bạn (tất cả các bài đăng trên mạng Stack Exchange được ký tự động).
drs

1
Cảm ơn bạn, giờ tôi đã học được cách gõ code as such!
hjkatz

Câu trả lời:


17

Từ trang người đàn ông:

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.

vì vậy bạn có thể đặt biến môi trường ZDOTDIRthành một thư mục mới để lấy zsh để tìm một tập hợp các dotfiles khác.

Như trang man gợi ý, RCSGLOBAL_RCSkhông phải là đường dẫn đến các tệp RC, vì bạn đang cố gắng sử dụng chúng, mà là các tùy chọn bạn có thể bật hoặc tắt. Vì vậy, ví dụ, cờ --rcssẽ kích hoạt RCStùy chọn, khiến zsh đọc từ các tệp RC. Bạn có thể sử dụng các cờ dòng lệnh sau để zsh để bật hoặc tắt RCShoặc GLOBAL_RCS:

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

Để trả lời câu hỏi khác của bạn:

có thể bắt đầu zsh, chạy "source / path / to / file", sau đó ở trong cùng một phiên zsh không?

Vâng, điều này là khá dễ dàng theo các hướng dẫn trên. Chỉ cần chạy zsh -d -fvà sau đó source /path/to/zshrc.


Vì điều này không hoạt động theo câu hỏi của tôi, tôi đã không đề cập đến việc tôi chỉ có thể chạy 1 lệnh. Điều này không đáp ứng những gì tôi muốn sử dụng cho (một ssh tùy chỉnh với cấu hình cá nhân của tôi). Vấn đề nằm ở chỗ việc chạy zsh -d -f; source /path/to/filekhông bao giờ thực thi lệnh thứ hai trong phiên đầu tiên của zsh cho đến khi thoát.
hjkatz

Trong toàn bộ, tôi muốn có thể làm như sau. sshđến một máy chủ từ xa "example.com", chạy zsh, sourcecấu hình của tôi nằm ở /path/to/file, tất cả trong 1 lệnh. Đây là nơi tôi đã vật lộn, đặc biệt là vì tôi không muốn ghi lại bất kỳ tệp cấu hình nào trên máy từ xa. Cảm ơn bạn đã trả lời mặc dù!
hjkatz

có vẻ như vấn đề của bạn không nằm ở việc sử dụng zshrc tùy chỉnh mà không biết cách sử dụng shell trên ssh. Nếu bạn chạy ssh host "zsh -d -f; source /path/to/file", thì ssh sẽ chạy đầu tiên zshtrên máy chủ từ xa, sau đó source ...khi vỏ zsh thoát. Thay vào đó, những gì bạn muốn làm là ssh -t host zsh -d -fthả vào một vỏ tương tác trên máy chủ từ xa hoặc nếu bạn không muốn một vỏ tương tác, hãy làm ssh host zsh -d -f -c \"source /path/to/file\; other command\; ... \".
jayhendren

Không tôi hiểu làm thế nào ssh hoạt động với vỏ tương tác. Vấn đề là việc chạy ssh -t host "zsh -d -f; source /path/to/filethả tôi vào một zshvỏ tương tác (và cằn cỗi) .
hjkatz

1
Tôi đã nói với bạn tại sao điều này là và cách khắc phục nó. Khi bạn chạy ssh -t host "zsh -d -f; source /path/to/file", lệnh source...KHÔNG chạy bên trong vỏ zsh. Nó chạy trong shell đăng nhập của bạn sau khi shell zsh thoát. Để kiểm tra điều này, chạy ssh host "zsh; echo foo". Bạn sẽ thấy đầu ra "foo" sau khi bạn thoát khỏi vỏ zsh.
jayhendren

4

trong khi với ZDOTDIR, bạn có thể yêu zshcầu giải thích một tệp được gọi .zshrctrong bất kỳ thư mục nào bạn chọn, việc nó diễn giải bất kỳ tệp nào bạn chọn (không nhất thiết phải gọi .zshrc) tỏ ra khá khó khăn.

Trong shhoặc kshthi đua, zshđánh giá $ENV; vì vậy bạn có thể thêm emulate zshở đầu của bạn /path/to/filevà làm:

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

Một cách tiếp cận rất phức tạp khác có thể là:

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

Điều đó xứng đáng một chút giải thích.

${foo::=value}là một mở rộng biến mà thực sự thiết lập $foo . $functionslà một mảng kết hợp đặc biệt ánh xạ tên hàm theo định nghĩa của chúng.

Với promptsubsttùy chọn, các biến trong $PS1được mở rộng. Vì vậy, theo dấu nhắc đầu tiên, các biến trong PS1 đó sẽ được mở rộng.

Các zsh_directory_namechức năng là một chức năng đặc biệt giúp mở rộng ~foođến /path/to/somethingvà ngược lại. Ví dụ, nó được sử dụng %~trong lời nhắc để nếu thư mục hiện tại là /opt/myproj/proj/xbạn có thể hiển thị nó ~proj:xbằng cách zsh_directory_namethực hiện ánh xạ proj:x<=> /opt/myproj/proj/x. Điều đó cũng được sử dụng bởi Dcờ mở rộng tham số. Vì vậy, nếu một mở rộng ${(D)somevar}, zsh_directory_namechức năng đó sẽ được gọi.

Ở đây, chúng tôi đang sử dụng ${(D):-}, ${:-}đó là ${no_var:-nothing}mở rộng nothingnếu $no_vartrống, vì vậy ${(D):-}mở rộng thành không có gì trong khi gọi zsh_directory_name. zsh_directory_nametrước đây đã được định nghĩa là:

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

Đó là, khi mở rộng PS1 đầu tiên (theo dấu nhắc đầu tiên), ${(D):-}sẽ khiến promptsubsttùy chọn không được đặt (hủy bỏ -o promptsubst), zsh_directory_name()không được xác định (vì chúng tôi chỉ muốn chạy nó một lần) $PS1để không được đặt và /path/to/fileđược cung cấp.

${PS1=%m%# }mở rộng (và gán $PS1) cho %m%#trừ khi PS1 đã được xác định (ví dụ /path/to/filesau sau unset) và %m%#tình cờ là giá trị mặc định của PS1.


Điều này có vẻ khá xa hoa và tôi sẽ thử nó càng sớm càng tốt. Tôi hy vọng điều này hoạt động!
hjkatz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.