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

时间:2013-06-23 19:19:24

标签: ruby zsh

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

1 个答案:

答案 0 :(得分: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从原始环境复制到您正在生成的任何新环境或shell中。

现在,最后一块拼图隐藏在Ruby源代码中,也隐藏在Kernel.exec的帮助文件中:

  

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

所以不,Unix上的Kernel.system或反引号不会运行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脚本并运行它。