我有一个在我的 zshenv 中声明为自动加载的函数。当我从 zsh 提示符或 zsh 脚本调用它时,它工作正常。但是当我尝试从 Ruby 脚本(使用`my_zsh_autoloaded_function`
)调用它时,它失败了。我知道 Ruby 正在使用 zsh,并且我知道正在获取 zshenv。一种解决方法是做`zsh -c "my_zsh_autoloaded_function"`
. 有没有办法让 Ruby 直接访问?
问问题
618 次
1 回答
6
你不能。这不是 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
只是从原始环境复制到您正在生成的任何新环境或外壳中。
现在拼图的最后一块隐藏在 Ruby 源代码中,也在Kernel.exec的帮助文件中:
标准 shell 在类 Unix 系统上总是表示“/bin/sh”,与 ENV["RUBYSHELL"](或 Windows NT 系列上的 ENV["COMSPEC"])相同,等等。
所以不,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
解决方案
像您一样运行 using zsh -c
,或者使用该命令创建一个单独的 Zsh shell 脚本并运行它。
于 2013-06-24T00:07:15.450 回答