我有一个函数在我的 zshenv 中声明为自动加载。当我从 zsh 提示符或 zsh 脚本调用它时,它工作正常。但是当我尝试从 Ruby 脚本调用它时(使用 `my_zsh_autoloaded_function`
),它失败了。我知道 Ruby 正在使用 zsh,而且我知道正在采购 zshenv。一种解决方法是执行 `zsh -c "my_zsh_autoloaded_function"`
。有没有办法让 Ruby 直接访问?
最佳答案
你不能。这不是 Unix 命令执行的方式。
Zsh 本质上是一个 REPL就像 irb
一样。
为了让 Zsh 执行内部命令,它必须执行以下操作之一:
- 从 REPL 循环 (STDIN) 中读取命令
- 使用
-c
开关执行命令,或者.. - 从 Zsh shell 脚本文件运行命令
当您只是执行 `zsh_function`
时,这些先决条件都不满足。
但是您实际上已经通过使用 zsh -c
找到了(其中一个)正确的解决方案。
但是您感到困惑,因为您正在查看 $SHELL
并认为您正在 zsh
下运行。 $SHELL
不是哪个 shell 正在运行的可靠指标:
> zsh
> echo $SHELL
/usr/bin/zsh
> sh
$ echo $SHELL
/usr/bin/zsh
$ bash
$ echo $SHELL
/usr/bin/zsh
$ SHELL=foo
$ bash
$ echo $SHELL
foo
因此 SHELL
只是从原始环境复制到您生成的任何新环境或 shell 中。
现在,最后一 block 拼图隐藏在 Ruby 源代码中,也隐藏在 Kernel.exec 的帮助文件中。 :
The standard shell always means "/bin/sh" on Unix-like systems, same as ENV["RUBYSHELL"] (or ENV["COMSPEC"] on Windows NT series), and similar.
所以不,Kernel.system
或 Unix 上的反引号不会运行 zsh
。它总是直接运行程序(例如 /bin/ls
)或运行 sh -c
在 bash 命令或需要任何其他 shell 处理的命令的情况下(如 ls *
)。
也很容易检查:
> zsh
> irb
> puts `ps xf; echo hello`
PID TTY STAT TIME COMMAND
24122 ? S 0:00 sshd: casper@pts/7
24127 pts/7 Ss 0:00 \_ -zsh
24686 pts/7 S 0:00 \_ zsh
24706 pts/7 Sl+ 0:00 \_ irb
24710 pts/7 S+ 0:00 \_ sh -c ps xf; echo hello
24712 pts/7 R+ 0:00 \_ ps xf
解决方案
要么像您一样使用 zsh -c
运行,要么使用命令创建一个单独的 Zsh shell 脚本并运行它。
关于ruby - 如何从 ruby 脚本访问自动加载的 zsh 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17264381/