如何从ruby脚本访问自动加载的zsh函数?

如何从ruby脚本访问自动加载的zsh函数?,ruby,zsh,Ruby,Zsh,我有一个在zshenv中声明为自动加载的函数。当我从zsh提示符或zsh脚本调用它时,它工作正常。但是当我尝试从Ruby脚本调用它时(使用`my_zsh_autoloaded_function`),它失败了。我知道Ruby正在使用zsh,我也知道zshenv正在采购中。一种解决方法是执行`zsh-c“my_zsh_autoloaded_函数”`。有什么方法可以让Ruby直接访问吗?你不能。这不是Unix命令执行的工作方式 Zsh本质上是一个类似于irb 为了让Zsh执行内部命令,它必须执行以下操

我有一个在zshenv中声明为自动加载的函数。当我从zsh提示符或zsh脚本调用它时,它工作正常。但是当我尝试从Ruby脚本调用它时(使用
`my_zsh_autoloaded_function`
),它失败了。我知道Ruby正在使用zsh,我也知道zshenv正在采购中。一种解决方法是执行
`zsh-c“my_zsh_autoloaded_函数”`
。有什么方法可以让Ruby直接访问吗?

你不能。这不是Unix命令执行的工作方式

Zsh本质上是一个类似于
irb

为了让Zsh执行内部命令,它必须执行以下操作之一:

  • 从REPL循环(STDIN)读取命令
  • 使用
    -c
    开关执行命令,或
  • 从Zsh shell脚本文件运行该命令
只要执行
`zsh\u函数`
,这些先决条件都不会得到满足

但实际上,您已经通过使用
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中

现在,拼图的最后一部分隐藏在Ruby源代码中,也隐藏在以下帮助文件中:

在类Unix系统上,标准shell始终表示“/bin/sh”,与ENV[“RUBYSHELL”](或Windows NT系列上的ENV[“COMSPEC”])和类似名称相同

因此,在Unix上,
Kernel.system
或backticks将不会运行
zsh
。它总是直接运行程序(例如
/bin/ls
),或者在bash命令或需要任何其他shell处理的命令(如
ls*
)的情况下运行
sh-c

也很容易检查:

> 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脚本并运行它。

您如何知道backticks正在执行
zsh
?@muistooshort``puts
echo$shell
`prints
/usr/local/bin/zsh
;我还可以访问
zshenv
中定义的backticks中的环境变量,感谢您的全面响应——非常有教育意义。不过,我确实发现有一件事不清楚——如果Ruby运行的是zsh而不是/bin/sh,那么在backticks中调用该函数就行了吗?您的回答的第一部分表明,除了使用backticks调用的shell不是zsh这一事实之外,还有一些原因表明这不起作用,但我不清楚这是什么原因。换句话说,/bin/sh是否可以通过backticks执行“内部命令”(不太确定什么是内部命令)。我想我可能没有用最好的方式来表达。你是对的。正如您所看到的,Ruby正在运行
sh
,并且带有
-c
标志。因此,如果Ruby使用
zsh
而不是
sh
,那么它是可以工作的,因为在这种情况下,
-c
条件将得到满足。答案很简单。这比实际情况要复杂一点,因为Ruby有一些内部逻辑来尝试检测哪些backtick参数是真正的内部
sh
命令,哪些不是(这样它就知道什么时候触发
-c
),但理论上是可以的。啊,我明白了,现在很有意义了。Ruby解析backticks输入并通过
sh-c
路由某些命令,在其他情况下直接调用程序。再次感谢@西恩马克西是正确的。您可以在此处查看相关代码: