8
votes

Script Source Shell dans l'environnement dans un script Ruby

Si j'écris un script shell et je veux "sourire" des scripts externes (c-) shell pour configurer mon environnement, je peux simplement faire des appels comme celui-ci:

#!/usr/bin/env ruby
system "~/test_script.csh"
system "echo $HAPPYTIMES"


3 commentaires

Qu'est-ce que vous obtenez si vous changez de script à cela? #! / usr / bin / env Fluby met env ['happytimes']


C'est une chose digne d'avoir accès aux fonctions de type OS telles que l'environnement de langues. Python a Os.environ, y a-t-il un module similaire à Ruby comme dans Python? cf Stackoverflow.com/Questtions/4906977/... & docs.python.org/2/library/os.html


Dupliqué possible de Shell sortant de Ruby tout en définissant une variable d'environnement


6 Réponses :


-4
votes
system 'source /file/I/want/to/source.sh'
Not sure that this will do what you want though. It will execute the source command in a subshell. Try it and see it it does what you're after.

3 commentaires

J'ai essayé ceci et il ne semble pas faire ce que je suis après. J'essaie d'obtenir les variables d'environnement définies par le script shell dans l'environnement, le script Ruby est en cours d'exécution.


Les changements d'environnement dans un processus d'enfant n'affectent pas le parent


Je pensais que cela pourrait être le cas. Désolée de vous avoir fait perdre votre temps.



1
votes

Vous allez devoir écrire une fonction pour exécuter quelque chose comme ce qui suit et capturer la sortie ("Backtick" opération): xxx

boucle sur chaque ligne, correspond à quelque chose comme xxx

puis utilisez la première capture de correspondance en tant que nom var, et la deuxième capture en tant que valeur var.

(oui, je suis couvert Le fait que je connaisse Perl bien mieux que de rubis, mais l'approche serait la même)


1 commentaires

En fait, ce que j'ai capturé toutes les variables d'environnement après avoir exécuté le script. IFF Les assignations dans le "script" n'ont aucune valeur interpolée, uniquement des littéraux à chaîne, vous pouvez obtenir ce que vous voulez simplement lire le fichier, plutôt que de devoir l'exécuter sur une pipe (backttick).



5
votes

La raison pour laquelle cela ne fonctionne pas pour vous est B / C Ruby exécute ses commandes système code> dans des coquilles séparées. Ainsi, lorsque la commande système se termine, la coque qui avait acheté votre fichier se ferme et toutes les variables d'environnement définies dans cette coque sont oubliées.

Si vous ne connaissez pas le nom du fichier source avant l'exécution, alors Réponse de la réponse est une bonne approche. Cependant, si vous connaissez le nom du fichier source à l'avance, vous pouvez faire un piratage rapide avec la ligne de hashbang. P>

% echo sourcer.rb
#!/usr/bin/env ruby
exec "csh -c 'source #{ARGV[0]} && /usr/bin/env ruby #{ARGV[1]}'"
% echo my-script.rb
#!/usr/bin/env ruby sourcer.rb /path/to/file/I/want/to/source.csh
puts "HAPPYTIMES = #{ENV['HAPPYTIMES']}"
% ./my-script.rb
HAPPYTIMES = True


1 commentaires

Je suppose que la seule raison pour laquelle cela fonctionne, disons, CSH, c'est que vous utilisez la même instance Shell pour interpréter le script que vous recherchez. Donc, vous ne pouviez pas rechercher un fichier .CSH à partir d'un script Bash, plus que vous ne pouvez l'obtenir d'un script Ruby ...



8
votes

Compte tenu de la rubis suivante

irb(main):019:0> source_env_from('test.sh')
=> {"FOO"=>"bar"}
irb(main):020:0> ENV['FOO']
=> "bar"


0 commentaires

3
votes

J'avais le même probrem. Et je résolve comme ci-dessous.

#!/usr/local/bin/ruby

def source(filename)
  ENV.replace(eval(`tcsh -c 'source #{filename} && ruby -e "p ENV"'`))
end

p "***old env*****************************"
p ENV
source "/file/I/want/to/source.csh"
p "+++new env+++++++++++++++++++++++++++++"
p ENV


1 commentaires

Vous devez faire très attention si nom de fichier est en fait ce que vous vous attendez à ce que ce soit; S'il s'agit d'une entrée de l'utilisateur, il s'agit d'une énorme fuite de sécurité ... Vous ne voulez généralement pas consigner des fichiers arbitraires, de sorte qu'un moyen plus sûr de le faire pourrait être d'assumer nom de fichier est un symbole, Et regardez cela dans un hachage (et s'il n'existe pas, lancez une erreur).



3
votes

Améliorer un peu sur la réponse de @ Takeccho ... Les chèques et quelques sifflets. Premièrement, l'environnement source est nettoyé via env -i , qui est une mesure de sécurité mais pourrait ne pas être souhaitée dans certains cas. Deuxièmement, via Set -A , toutes les variables définies dans le fichier sont "exportées" de la coque et donc importées en rubis. Ceci est utile pour la simulation / le comportement de simulation / dépassement trouvé dans les fichiers d'environnement utilisés avec des scripts init et SystemD env fichiers. XXX

Théorie de l'opération: Lorsque Ruby sortit l'objet env en utilisant p , il le fait de manière à ce que Ruby puisse la lire en tant qu'objet. Nous utilisons donc la coquille pour rechercher le fichier cible et Ruby (dans une sous-coquille) pour émettre l'environnement de cette forme sérialisable. Nous capturons ensuite la sortie de Ruby et eval dans notre processus de rubis. Il est clair que cela n'est pas sans risque, afin d'atténuer le risque, nous (1) validons le nom de fichier qui est transmis, et (2) valider à l'aide d'un regexp que la chose que nous recevons du Subshell-ruby est, en fait, une chaîne de hachage sérialisable. Une fois que nous en sommes sûrs, nous faisons le eval qui crée un nouveau hachage. Nous fusionnons ensuite "manuellement" fusionnez le hash avec env , qui est un objet objet et non un hash . S'il s'agissait d'un hachage, nous aurions pu utiliser la méthode #merge! .

EDIT: SH -A EXPORTUÉS COMME PATH < / code>. Nous devons également supprimer shlvl et pwd avant la fusion de hachage.


0 commentaires