Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
&引用;资料来源;在ruby子壳中_Ruby_Shell - Fatal编程技术网

&引用;资料来源;在ruby子壳中

&引用;资料来源;在ruby子壳中,ruby,shell,Ruby,Shell,我需要从ruby应用程序运行shell命令。我使用的是system(),但这也适用于反勾号 在运行命令时,我需要首先加载一个shell脚本来设置一些内容,因此我尝试以下方法: system("source my_script.sh && my_command") 在我的Mac笔记本电脑上,这可以按预期工作,但在我的ubuntu服务器上,我得到: sh: 1: source: not found 我想知道其中的“sh”,因为我的shell应该是bash,所以尝试了以下方法: s

我需要从ruby应用程序运行shell命令。我使用的是
system()
,但这也适用于反勾号

在运行命令时,我需要首先加载一个shell脚本来设置一些内容,因此我尝试以下方法:

system("source my_script.sh && my_command")
在我的Mac笔记本电脑上,这可以按预期工作,但在我的ubuntu服务器上,我得到:

sh: 1: source: not found
我想知道其中的“sh”,因为我的shell应该是bash,所以尝试了以下方法:

system("echo $SHELL && source my_script.sh && my_command")
这给了我:

/bin/bash
sh: 1: source: not found
因此,它使用的是正确的shell,但出于某种原因,
source
不起作用

为什么??我能做些什么呢

更新 正如Sergio Tulentsev指出的,Ruby不一定使用$shell中设置的shell

这给了我ruby实际使用的shell:

system("ps -p $$ | tail -1 | awk '{print $NF}'")
sh
 => true

因此,它使用的是sh。我可以强制它使用bash吗?

您需要尝试在要源文件的前面添加
/
,如果子SHELL是bash,这应该可以工作(选中
$SHELL


如果
$SHELL
sh
,则需要执行
/test.sh
而不是
source./test.sh
,因为source关键字仅为bash

或者,您可以通过执行以下操作来确保您正在使用bash:

irb(main):007:0> system("/bin/bash -c 'source ./test.sh && echo $TEST && cat test.sh'")
test
export TEST=test
=> true

正如其他人所指出的,Ruby使用
sh
作为其子shell。使用bash的一种方法是类似于
system(“/bin/bash-c'…”)
,这会导致各种转义问题。相反,我决定使用Open3生成一个“真正的”进程,在其中运行bash并将我的命令导入其中。工作起来很有魅力:

require "open3"

# using bash --login to ensure the same env as usual
Open3.popen3('/usr/bin/env bash --login') do |stdin, stdout, stderr, wait_thr|
  pid = wait_thr[:pid]

  stdin.puts("cd some_directory")
  stdin.puts("source some_script")
  stdin.puts("some_command")

  # don't forget to close it again
  stdin.puts("exit")

  # for debug purposes
  stdout.each_line do |line|
    puts "STDOUT: " + line
  end

  stdin.close
  stdout.close
  stderr.close
end
这看起来有点过分,但它允许对子进程的控制实际上是非常好的


谢谢大家的建议。

如果
$SHELL
设置为bash,我想这并不一定意味着ruby会使用它。试试这个技巧来确定实际的外壳:哦,我不知道。但是是的,它实际上是“sh”。谢谢。如果
$SHELL
sh
,那么
源代码
将无法工作,您需要反编译
。file.sh
来获取它的源代码不是这样的。即使使用绝对路径,它也不起作用。谢谢,这种方法很有效,但会让我逃避命令字符串的问题。我想我将使用Open3生成
/usr/bin/env bash
,以更好地控制它。这听起来是个好主意。至于转义,您可能应该包装您的Open3调用,所以它会处理这个问题。您对转义问题有很好的看法。但是你展示的代码也展示了那些逃避问题,不是吗?当我所做的只是将命令放在stdin上时,我不知道如何通过数组获得安全转义命令语法。也许我错过了什么。
require "open3"

# using bash --login to ensure the same env as usual
Open3.popen3('/usr/bin/env bash --login') do |stdin, stdout, stderr, wait_thr|
  pid = wait_thr[:pid]

  stdin.puts("cd some_directory")
  stdin.puts("source some_script")
  stdin.puts("some_command")

  # don't forget to close it again
  stdin.puts("exit")

  # for debug purposes
  stdout.each_line do |line|
    puts "STDOUT: " + line
  end

  stdin.close
  stdout.close
  stderr.close
end