2014-03-25 24 views
2

我需要從ruby應用程序運行shell命令。我正在使用system(),但這也適用於反引號。紅寶石子殼中的「源」

當運行我的命令,我需要先裝一個shell腳本,設置了一些事情,所以我嘗試這樣:

system("source my_script.sh && my_command") 

在我的Mac筆記本電腦這種按預期工作,但在我的Ubuntu的服務器I得到:

sh: 1: source: not found 

我想知道在那裏 「sh」 的,因爲我的外殼應該是一個bash,所以嘗試這樣做:

system("echo $SHELL && source my_script.sh && my_command") 

這給了我:

/bin/bash 
sh: 1: source: not found 

所以,它是使用合適的外殼,但由於某些原因,source不起作用。

爲什麼?我能做些什麼呢?

更新 正如Sergio Tulentsev指出的那樣,Ruby不一定使用在$ SHELL中設置的shell。

這使我的紅寶石是用實際的外殼:

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

所以,它用sh。我可以以某種方式強制它使用bash?

+2

如果'$ SHELL'被設置爲bash,我認爲這並不意味着ruby會使用它。試試這個技巧來確定實際的shell:http://liquidat.wordpress.com/2007/07/28/short-tip-determine-current-shell/ –

+0

哦,我不知道。但是,是的,它實際上是「sh」。謝謝。 – selfawaresoup

+1

如果'$ SHELL'是'sh',那麼'source'將不能工作,你需要de'。文件。sh'來源 – jbr

回答

1

你需要嘗試在你想要的源代碼文件前添加./,如果子shell是bash,那麼它應該工作(檢查$SHELL)。

irb(main):003:0> system("source ./test.sh && echo $TEST && cat test.sh") 
test 
export TEST=test 
=> true 

如果$SHELLsh,那麼你需要做的. ./test.sh,而不是source ./test.sh,作爲源參數僅是bash的。

或者你可以確保你正在使用bash,這樣做:

+0

不,不是的,不是。即使採用絕對路徑也行不通。 – selfawaresoup

+0

我已經更新了另一個建議:-) – jbr

+0

謝謝,那種工作,但帶來了我用我的命令字符串逃避問題。我想我會用Open3產生'/ usr/bin/env bash'以更好地控制它。 – selfawaresoup

1

正如其他人所指出的那樣,紅寶石使用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 

這似乎是有點矯枉過正,但它允許在子過程的控制實際上是相當不錯的。

謝謝大家的建議。