3

我有一个在我的 zshenv 中声明为自动加载的函数。当我从 zsh 提示符或 zsh 脚本调用它时,它工作正常。但是当我尝试从 Ruby 脚本(使用`my_zsh_autoloaded_function`)调用它时,它失败了。我知道 Ruby 正在使用 zsh,并且我知道正在获取 zshenv。一种解决方法是做`zsh -c "my_zsh_autoloaded_function"`. 有没有办法让 Ruby 直接访问?

4

1 回答 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 回答