2011-11-28 3 views
18

Ho bisogno di eseguire il bombardamento su un processo mentre si imposta una variabile di ambiente per esso. Ho provato questo one-liner:Shell fuori dal rubino durante l'impostazione di una variabile di ambiente

system "RBENV_VERSION=system ruby extconf.rb" 

Questa sintassi funziona in script di shell, ma non da rubino. (Aggiornamento:. risulta questa sintassi funziona dal rubino, dopo tutto, ma non sono riuscito a vedere il suo effetto dovuto al mio particolare caso d'uso)

così sto facendo questo:

rbenv_version = ENV['RBENV_VERSION'] 
ENV['RBENV_VERSION'] = 'system' 
begin 
    system "ruby extconf.rb" 
ensure 
    ENV['RBENV_VERSION'] = rbenv_version 
end 

Sono costretto a un'espressione così lunga perché non voglio sovrascrivere la variabile di ambiente in modo permanente se ha già un valore.

Qualcosa di più breve che ti viene in mente?

risposta

63
system({"MYVAR" => "42"}, "echo $MYVAR") 

system accetta alcun argomento che Process.spawn accetta.

+1

You da man. \ o/ – mislav

+0

Questa è un'ottima risposta. La documentazione per ['Kernel # system'] (http://ruby-doc.org/core-1.9.3/Kernel.html#method-i-system) non è sufficientemente chiara su questa funzionalità. Molto bella. – Phrogz

+0

Per Ruby 1.8, guarda POSIX :: Spawn di @ rtomayko, collegato in un altro commento. – alxndr

2

Questo potrebbe funzionare?

system <<-CMD 
export VARNAME=123 
other_command 
CMD 
+1

Che funziona. Una riga: esportazione 'system' VARNAME = 123 && other_command'' – mislav

6

Ruby 1.9 include Process::spawn che consente di fornire un hash ambientale.

Process::spawn è anche il fondamento per system, exec, popen, ecc
È possibile passare un ambiente a ciascuno.

Sotto Ruby 1.8, si può prendere in considerazione la biblioteca POSIX::Spawn,
che fornisce le stesse interfacce

+0

Buono a sapersi! Ma l'invocazione è piuttosto clunky: 'Process.wait Process.spawn ({" MYVAR "=>" 42 "}," echo $ MYVAR ")' per le mie semplici esigenze. Risulta che la funzione 'system' supporta anche questo argomento hash opzionale! – mislav

+0

'system' accetta tutti gli argomenti che' Process.spawn() 'accetta. Vedi la mia risposta per esempio. – Avdi

3

Utilizzando il medesimo approccio, ma avvolto come un metodo di blocco che modifica temporaneamente l'ambiente (come la forma del blocco di Dir.chdir):

def with_environment(variables={}) 
    if block_given? 
    old_values = variables.map{ |k,v| [k,ENV[k]] } 
    begin 
     variables.each{ |k,v| ENV[k] = v } 
     result = yield 
    ensure 
     old_values.each{ |k,v| ENV[k] = v } 
    end 
    result 
    else 
    variables.each{ |k,v| ENV[k] = v } 
    end 
end 

with_environment 'RBENV_VERSION'=>'system' do 
    `ruby extconf.rb` 
end 
+0

Uso spesso tale approccio nei test, ma qui è eccessivo. – mislav

+0

@AnonymousDownvoter Ti incoraggio a ridiscutere le risposte che sono _wrong_ e a rispedire le risposte che sono migliori di altre.Downvoting di una risposta (corretta) presumibilmente perché ci sono altre risposte che sono migliori (più facile, più breve) non è nello spirito di Stack Overflow, IMHO. – Phrogz

+0

+1 prima, per ottenere un ingiusto downvote. 2 °, perché questa è la mia risposta preferita. Ero più eccitato fino a quando mi sono reso conto che avevi definito: with_environment. È triste, perché questo è il metodo che dovrebbe esistere in Ruby stessa. –

3

In realtà ciò ha funzionato per me.

[email protected] ~ » irb                                  
1.9.3p0 :001 > system %{SHAIGUITAR=exists ruby -e 'puts ENV["SHAIGUITAR"]'} 
exists 
=> true 

Ma se così non fosse, forse si può provare a prependere "env" a qualsiasi variabile di cui si ha bisogno. Per esempio.

system(%{env SHAIGUITAR=exists ruby bla.rb}) 
+0

Funziona anche per me. Sono un idiota, l'ho provato e l'ho scartato dopo che non ho ottenuto l'effetto desiderato, ma è stato a causa del mio particolare caso d'uso e non perché non è supportato. Grazie! – mislav

+0

L'unica cosa che non funziona con questo - e questo è molto strano - è l'esempio "echo". Ecco perché contrassegno l'altra risposta come corretta: copre più casi. – mislav