Ulepszanie odpowiedzi @ takeccho ... Czeki i kilka gwizdów. Po pierwsze, środowisko źródłowe jest czyszczone przez env -i
, co jest środkiem bezpieczeństwa, ale w niektórych przypadkach może być niepożądane. Po drugie, poprzez set -a
, wszystkie zmienne ustawione w pliku są "eksportowane" z powłoki i tym samym importowane do ruby. Jest to przydatne do symulacji/przesłonięcia zachowania w plikach środowiskowych używanych w skryptach init i plikach env systemd.
def ShSource(filename)
# Inspired by user takeccho at http://stackoverflow.com/a/26381374/3849157
# Sources sh-script or env file and imports resulting environment
fail(ArgumentError,"File #{filename} invalid or doesn't exist.") \
unless File.exist?(filename)
_newhashstr=`env -i sh -c 'set -a;source #{filename} && ruby -e "p ENV"'`
fail(ArgumentError,"Failure to parse or process #{filename} environment")\
unless _newhashstr.match(/^\{("[^"]+"=>".*?",\s*)*("[^"]+"=>".*?")\}$/)
_newhash=eval(_newhashstr)
%w[ SHLVL PWD _ ].each{|k|_newhash.delete(k) }
_newhash.each{|k,v| ENV[k]=v } # ENV does not have #merge!
end
Teoria działania: Kiedy ruby wysyła przedmiot ENV korzystając p
, robi to w taki sposób, że rubin można odczytać z powrotem w jako obiekt. Tak więc używamy powłoki do źródła pliku docelowego i ruby (w podrzędnej powłoce), aby wyprowadzać środowisko w tej postaci szeregowej. Następnie przechwytujemy wyniki ruby i eval
w ramach naszego procesu ruby. Oczywiście nie jest to bez ryzyka, więc aby złagodzić ryzyko, (1) sprawdzamy poprawność podanej nazwy pliku i (2) sprawdzamy za pomocą wyrażenia regularnego, że rzecz, którą otrzymujemy z podpowłoki ruby, jest w rzeczywistości serializowany ciąg mieszający. Gdy jesteśmy tego pewni, robimy eval
, który tworzy nowy skrót. Następnie "ręcznie" scalamy hash z ENV
, który jest Object
, a nie zwykłym Hash
. Jeśli byłaby to mieszanka, moglibyśmy użyć metody #merge!
.
EDYTOWANIE: sh -a
wyeksportowane elementy, takie jak PATH
. Musimy również usunąć przed scaleniem mieszania SHLVL
i PWD
.
Co otrzymasz, jeśli zmienisz scenariusz na ten? #!/Usr/bin/env ruby stawia ENV ['HAPPYTIMES'] – Henry
to godna rzecz, aby uzyskać dostęp do funkcji typu systemu operacyjnego, takich jak ustawienia środowiska z języków. Python ma os.environ, czy istnieje podobny moduł w Ruby jak w python? cf http://stackoverflow.com/questions/4906977/python-environment-variables & http://docs.python.org/2/library/os.html – bootload
możliwy duplikat [Shell out from ruby podczas ustawiania zmiennej środowiskowej ] (http://stackoverflow.com/questions/8301294/shell-out-frub-ruby-while-setting-an-environment-variable) – durron597