Chuyển các biến môi trường tới trình điều khiển trình bao lang thang


77

Có vẻ như việc chuyển các biến môi trường khi gọi vagrant uprất đơn giản nếu bạn đang sử dụng trình cấp phép Ruby:

VAR=123 vagrant up

Trong Vagrantfile:

ENV['VAR']

Làm cách nào để làm điều này với người :shellcung cấp? Chỉ đơn giản làm điều này dường như không hoạt động:

$VAR

Câu trả lời:


81

Kể từ Vagrant 1.8.0, bạn có thể quên đi những vụ hack xấu xí từ các câu trả lời khác ở đây. Chỉ cần sử dụng envtùy chọn cho trình cung cấp shell ( tài liệu ).

Sử dụng nó như thế này trong Vagrantfile của bạn:

config.vm.provision "shell", path: "provisionscript.sh", env: {"MYVAR" => "value"}

Điều này sẽ thiết lập môi trường chỉ cho tập lệnh cấp phép. Nếu bạn cần một biến môi trường liên tục được đặt cho tất cả các quy trình trong VM, điều này nằm ngoài phạm vi cấp phép của Vagrant và hãy xem tại đây: Các biến môi trường Shell trong các tệp vagrant chỉ được chuyển lên trước .


Trong Vagrant 1.8.5, envtham số dường như chỉ hoạt động khi sử dụng pathtập lệnh, không phải inlinetập lệnh.
spyle

1
@spyle Tôi đang chạy Vagrant 1.8.5 (với VirtualBox 5.1.2 trên Mac OS X 10.11.6) và envhoạt động với inline.
jonatan

Hmm ... tôi có thiếu cái gì ở đây không? Đây không phải là làm việc cho tôi: config.vm.provision :shell, path: "bootstrap.sh", env: {"MYSQL_DB_USERNAME"=>"django", "MYSQL_DB_PASSWORD"=>"supersecretpasswordwasreplaced"} Ở phía bên kia os.environ['MYSQL_DB_USERNAME'] đưa ra một lỗi quan trọng :(
Tadhg

1
@Tadhg Kiểm tra kỹ phiên bản Vagrant của bạn. Và có lẽ hãy hỏi một câu hỏi mới nếu nó không hoạt động? Đó có thể là một vấn đề không liên quan (ví dụ: phiên bản Vagrantfile hoặc môi trường không được lưu giữ trong chuỗi công cụ của bạn).
gertvdijk

Phiên bản là tốt. Bạn nói đúng, nhìn vào tài liệu, có vẻ như cấu hình này chỉ được cho là hoạt động ở thời gian cấp phép, vì vậy tôi đã hỏi đây là một câu hỏi mới stackoverflow.com/questions/40270391/…
Tadhg

42

Nó không phải là lý tưởng, nhưng tôi phải làm việc này ngay bây giờ:

config.vm.provision "shell" do |s|
    s.inline = "VAR1 is $1 and VAR2 is $2"
    s.args   = "#{ENV['VAR1']} #{ENV['VAR2']}"
end

3
Bạn cũng có thể thay thế s.inlinebằng s.pathvà sử dụng cùng một tập lệnh mà bạn đã sử dụng :path => "". (Provisioner tôi là hàng trăm dòng và do đó bị bệnh phù hợp với nội tuyến.)
msanford

3
Ngoài ra, sử dụng phương thức ruby ​​với một :args => ""tham số, như vậy .
msanford

4
Bạn thực sự nên có một dấu phẩy bên trong s.args?
Marius Gedminas

17

Đối với hậu thế (hay còn gọi là trong trường hợp tôi google lại) ... Có thể chuyển các cặp khóa-giá trị qua env :

box.vm.provision :shell do |s|
  s.env = {AWS_ACCESS_KEY:ENV['AWS_ACCESS_KEY'], AWS_SECRET_KEY:ENV['AWS_SECRET_KEY']}
  s.path = 'scripts/bootstrap.sh'
end

Sau đó tham chiếu chúng trong tập lệnh của bạn:

export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY}
export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_KEY}

Tính năng thưởng:

Vagrant sẽ xử lý trích dẫn cho các giá trị biến môi trường, nhưng các khóa vẫn không bị ảnh hưởng


Cũng xem câu trả lời đăng bởi @gertvdijk (Tôi không có trang web của tôi làm mới khi gửi bài)
Al Belsky

16

Tôi đã đưa ra giải pháp này để cung cấp dựa trên CentOS: đặt tất cả các biến môi trường bắt buộc của tôi trong /etc/profile.d/vagrant.shtệp và sau đó nó được truy cập trong bất kỳ tập lệnh cung cấp nào.

Nói ngắn gọn:

  $before_script = <<SCRIPT
  echo # vagrant profile script > /etc/profile.d/vagrant.sh
  echo export ENV_VAR1=foo.com/bar >> /etc/profile.d/vagrant.sh
  echo export ENV_VAR2=bar.com/foo >> /etc/profile.d/vagrant.sh
  chmod +x /etc/profile.d/vagrant.sh
SCRIPT

  $after_script = <<SCRIPT
    rm -rf /etc/profile.d/vagrant.sh
SCRIPT

  config.vm.provision "shell", inline: $before_script
  config.vm.provision "shell", path: "build.sh"
  config.vm.provision "shell", inline: $after_script

Toàn bộ Vagrantfilecó thể được tìm thấy ở đây https://gist.github.com/bivas/6192d6e422f8ff87c29d


Hoạt động cho tôi trong Linux (cho một máy ảo dựa trên Ubuntu). Tuyệt vời!
Nikos Alexandris

1
Mặc dù vậy, hiện đã có vagrantup.com/docs/provisinstall/shell.html#env . Tôi đã thấy nó nhưng do thiếu ví dụ nên tôi đã bỏ qua. Một đồng nghiệp đã chỉ ra rằng nó hoạt động.
Nikos Alexandris

1
@NikosAlexandris: Xem câu trả lời của tôi :)
gertvdijk

8

Bạn có thể sử dụng #{ENV['VAR']}bên trong một tập lệnh nội tuyến, ví dụ:

config.vm.provision "shell", inline: <<-END
  ...
  # Install my dotfiles are there.  If you're in a hurry you can do
  # SKIP_DOTFILES=1 vagrant up
  if ! [ -d /home/vagrant/dotfiles ] && [ -z '#{ENV['SKIP_DOTFILES']}']; then
    if ! [ -x /usr/bin/git ]; then
      DEBIAN_FRONTEND=noninteractive apt-get install -y git
    fi
    su - vagrant -c 'git clone https://github.com/mgedmin/dotfiles'
    su - vagrant -c 'dotfiles/install.sh'
  fi
  ...
  END

Ví dụ được lấy từ một Vagrantfile đang hoạt động.

Điều này có một số nhược điểm: nếu $ VAR chứa các dấu nháy đơn, mọi thứ sẽ bị hỏng.


Tất nhiên, tôi nhận thấy rằng @Bob về cơ bản đã cung cấp cùng một câu trả lời (trong bit CÁCH MỚI) ngay sau khi tôi đăng bài của mình. Mặc dù!
Marius Gedminas

7

Trong trường hợp ai đó kết thúc việc tìm kiếm cách đặt các biến trong môi trường của tập lệnh cung cấp, điều này đã hiệu quả với tôi.

config.vm.provision :shell, :inline => <<-SH
  export GRAPHITE_HOST=192.168.33.10
  /vagrant/install_app_with_monitoring.sh
SH

Lưu ý rằng điều này giả sử bạn đang chia sẻ thư mục làm việc của mình như /vagranttrên máy ảo nhưng đây phải là mặc định.


nhưng tại sao không làm điều này bên trong install_app_with_monitoring.sh?
Stephan Bijzitter,

Chủ yếu để giữ kiến ​​thức ở cùng một nơi. Bạn có thể xem một ví dụ ở đây github.com/forty9ten/monitoring-with-graphite/blob/master/… Bằng cách giữ var trong Vagrantfile, thật dễ dàng để đảm bảo tính chẵn lẻ giữa private_networkGRAPHITE_HOST. Thậm chí có thể tiến thêm một bước nữa và sử dụng export GRAPHITE_HOST=#{ip}để tham chiếu đến một var ruby ​​chung duy nhất.
Mat Schaffer

5

Hầu hết những câu trả lời này dường như đã lỗi thời. Với Vagrant 2.1.1, điều này đã làm việc cho tôi:

  VAGRANTFILE_API_VERSION = "2" //...

  machine.vm.provision "shell", 
    env: {
      "ELASTIC_XMS" => servers["elastic"]["memory_xms"], 
      "ELASTIC_XMX" => servers["elastic"]["memory_xmx"]
    }, 
    inline: "sed -i -e \"s/-Xms.*/$ELASTIC_XMS/g\" /etc/elasticsearch/jvm.options"

2

Các lang thang-env Plugin không chính xác này. Với nó, bạn có thể thêm các biến môi trường vào .envtệp trong thư mục cục bộ sẽ được tải trong Vagranttệp. Tôi đề nghị giữ .envtrong của bạn .gitignore, bằng cách này, bạn có quyền riêng tư của bạn được đảm bảo.


1
Plugin đã chết vào năm 2015, đây không phải là hiện tại.
Ligemer

1

Đây là cách tôi có nó hoạt động.

Tôi đã đi từ việc sử dụng cách cung cấp con rối lang thang sang chỉ sử dụng trình cung cấp vỏ. Tôi đã làm điều này chủ yếu vì tôi muốn bù nhìn không chạy dưới quyền root, nhà cung cấp trình bao cung cấp cho bạn: đặc quyền => false.

CÁCH CŨ CỦA TÔI:

config.vm.provision :puppet do |puppet|
  puppet.module_path = ENV.fetch('MODULES_PATH', 'modules')
  puppet.manifests_path = ENV.fetch('MANIFESTS_PATH', 'manifests')
  puppet.manifest_file  = ENV.fetch('MANIFEST_FILE', 'site.pp')
  puppet.options = "--debug"
end

CÁCH MỚI CỦA TÔI:

config.vm.provision :shell, :privileged => false do |shell|
  shell.inline = "puppet apply --debug --modulepath '/vagrant/#{ENV.fetch('MODULES_PATH', 'modules')}' --detailed-exitcodes '/vagrant/#{ENV.fetch('MANIFESTS_PATH', 'manifests')}/#{ENV.fetch('MANIFEST_FILE', 'site.pp')}'"
end

1

Bạn chỉ cần chỉ định để shellsử dụng inlinetrong Vagrantfiletệp của mình :

config.vm.provision "shell", inline: %Q(/usr/bin/env FOO=1 BAR=1 bash /path/to/script.sh)

Hoặc tải một số biến bổ sung từ tệp YAML:

require 'yaml'
dir = File.dirname(File.expand_path(__FILE__))
vconfig = YAML::load_file("#{dir}/config.yml")
config.vm.provision "shell", inline: %Q(/usr/bin/env FOO=#{vconfig['foo']} bash /path/to/script.sh)

Ngoài ra, bạn có thể triển khai một số đối số tùy chọn từ dòng lệnh, ví dụ:

# Parse optional arguments.
opts = GetoptLong.new(
  [ '--foo',  GetoptLong::OPTIONAL_ARGUMENT ], # With optional parameter.
  [ '--bar',  GetoptLong::OPTIONAL_ARGUMENT ], # With optional parameter.files.
)
opts.each do |opt, arg|
  case opt
    when '--foo'
      foo==arg
    when '--bar'
      bar=arg
  end
end

sau đó sử dụng: opt['--foo'].to_s.

Xem thêm: Làm thế nào để truyền tham số trên Vagrant lên và có nó trong phạm vi của sách nấu ăn Chef?


-2

điều này đã làm việc cho tôi

VAGRANTFILE_API_VERSION = "2"

kettle_dir = ENV['KETTLE_DIR']
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   config.vm.synced_folder kettle_dir, "/pentaho"
   config.vm.box = "ubuntu/trusty64"
end

Bạn có thể đưa ra một số chi tiết để chỉ ra tại sao đây là câu trả lời chính xác?
rfornal

Điều này sử dụng một biến môi trường trong Vagrantfile, nhưng không thực sự đặt một biến môi trường cho người cung cấp như đã hỏi trong câu hỏi.
btubbs

-3

Trên hộp ubutnu, tôi chỉ cần thực hiện như sau trong bootstrap.sh của mình:

echo "DBHOST=localhost" >> /etc/environment
echo "DBNAME=foo" >> /etc/environment
echo "DBUSER=root" >> /etc/environment
echo "DBPASSWD=root" >> /etc/environment
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.