2010-01-26 9 views
5

Próbuję uruchomić skrypty bash strony trzeciej z poziomu mojego programu ruby.Jak pozyskać zmienne środowiskowe dla powłoki poleceń w skrypcie Ruby?

Zanim będę mógł je uruchomić, wymagają ode mnie pobrania pliku. W linii poleceń wszystko działa dobrze, ale w Ruby nie działa. Dowiedziałem się, że polecenia systemowe otworzą nowy proces powłoki podrzędnej, a wszelkie pozyskiwanie zostanie wykonane w tym procesie i nie będzie można go zobaczyć z procesu powłoki nadrzędnej, w którym uruchomiony jest skrypt języka Ruby. Po zakończeniu wywołania systemowego powłoka podrzędna również zostaje zabita.

Jak obejść ten problem?

Odpowiedz

7

Wykonaj:

$ source whatever.sh 
$ set > variables.txt 

A następnie w języku Ruby:

File.readlines("variables.txt").each do |line| 
    values = line.split("=") 
    ENV[values[0]] = values[1] 
end 

Po uruchomieniu tego środowiska powinno być dobrze.

+0

Spróbuj tego. Czy oznacza to, że skrypt może zmienić zmienne środowiskowe jego zawierającego proces powłoki, a zatem wszelkie dalsze procesy podrzędne utworzone przez wywołania systemowe z dziedziczeniem? – robodisco

+1

Nie, ale każdy proces wykonany ze skryptu Ruby odziedziczy zmienne skryptu. – Geo

+0

Powyższe działa dla pojedynczego wątku, a ja wykonuję poniższe czynności. Ale mam pytanie, jak mogę wykorzystać połączoną kopię środowiska z IO.popen? jakoś to nie działa. z "systemem" mogę zrobić: # ... utworzyć nową "ścieżkę" tutaj subEnv = Hash.new; subEnv.merge! (ENV); # copy old environment subEnv ['PATH'] = ścieżka; # ustaw nowe wartości w kopii system (subEnv, commandLine); – peterk

2

Nie jestem pewien, czy dobrze rozumiem twoje pytanie. Czy próbujesz pozyskać skrypt powłoki przed uruchomieniem innego? W tym przypadku odpowiedź jest prosta:

#!/bin/env ruby 
system "source <path_to_source_file> && <command>" 

Jeśli plik źródłowy zawiera zmienne, które swoją komenda powinny używać trzeba je export. Możliwe jest także ustawienie zmiennych środowiskowych w swoim skrypcie Ruby za pomocą ENV['<name_of_var>'] = <value>.


Aktualizacja: 26 stycznia 2010 - 15:10

Można użyć IO.popen otworzyć nową powłokę:

IO.popen("/bin/bash", "w") do |shell| 
    shell.puts "source <path_to_source_file>" 
    shell.puts "<command>" 
end 
+0

Nie sądzę, że Wykonanie z systemem pomoże, bo Vars zostanie ustawiona tylko dla procesu powłoki który pobiera zrodził do wykonania tego polecenia. – Geo

+0

Nie mogę nawet uzyskać "source .bashrc" systemu do pracy w moim katalogu użytkownika. Narzeka, że ​​polecenie nie zostało znalezione. Czy na pewno można użyć źródła takiego, jakie opublikowałeś? – robodisco

+0

To zadziałało dla mnie. Próbowałem tego na OSX 10.6. Czy powłoka użytkownika, który wykonuje skrypt ustawiony na/bin/bash? (Zaktualizowałem również moją odpowiedź.) – t6d

0

Zrobiłem to, bo nie chcą mieć zapisać plik lub mieszać mojego kodu Ruby z tych rzeczy:

#!/usr/bin/env bash 
eval $(echo "$(cat .env) $1" | tr '\n' ' ') 

Ja to w ~/bin/run_with_env.sh a następnie przez przykładem może uruchomić:

% run_with_env.sh "rails console" 
2

to jest straszne, ale ..

env = %x{. /some/shell/script/which/setups/your/env && env} 
env.split("\n").each do |line| 
    key, value = line.split("=", 2) 
    ENV[key] ||= value unless value.nil? or value.empty? 
end 
0

Modyfikowanie ENV działa tylko na jednym wątku i zrobić bel ow zamiast tego. Ale mam pytanie, jak mogę wykorzystać połączoną kopię środowiska z IO.popen? jakoś to nie działa.

z „systemu” Mogę zrobić:

# ... create new "path" here 

    subEnv = Hash.new; 
    subEnv.merge!(ENV); # copy old environment 
    subEnv['PATH'] = path; # set new values in copy 

    system(subEnv, commandLine);