Vagrant+シェルでRails開発サーバを作る
新規案件でRails開発サーバを準備する必要があり、Vagrantとシェルのプロビジョニングで作成したときのメモです。
プロビジョニングにシェルを使用したのは、開発用PCがWindowsのためです。
無理してchefとか使おうとすると、環境構築を楽にするための環境構築が大変になるというよくわからないことになりそうでしたので。
下記ページを大いにパクらせて参考にさせていただきました。多謝です!
Rails開発のための仮想環境をvagrantでつくる - Qiita
主にインストールされるもの
- CentOS 6.7
- MySQL 5.6
- sqlite
- memcached
- rbenv
- ruby 2.3.1
- Git
- vim
- Nokogiriに必要なライブラリ
- ImageMagickに必要なライブラリ
※CentOS7/MySQL5.7の罠は回避。
よし作ろう
前提:VirtualBoxとVagrantはインストール済
1.boxファイルを取得
vagrant box add CentOS_6_7 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box
2.初期設定
cd ~ mkdir centos6-rails cd centos6-rails vagrant init CentOS_6_7
3.Vagrantfileを作成
下記のように書き換える
# -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| GUEST_RUBY_VERSION = '2.3.1' # The most common configuration options are documented and commented below. # For a complete reference, please see the online documentation at # https://docs.vagrantup.com. config.ssh.username = "vagrant" config.ssh.password = "vagrant" # Every Vagrant development environment requires a box. You can search for # boxes at https://atlas.hashicorp.com/search. config.vm.box = "CentOS_6_7" config.vm.hostname = "centos6-rails" # Disable automatic box update checking. If you disable this, then # boxes will only be checked for updates when the user runs # `vagrant box outdated`. This is not recommended. # config.vm.box_check_update = false # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine. In the example below, # accessing "localhost:8080" will access port 80 on the guest machine. # config.vm.network "forwarded_port", guest: 3000, host: 3000 # Create a private network, which allows host-only access to the machine # using a specific IP. config.vm.network "private_network", ip: "192.168.33.10" # Create a public network, which generally matched to bridged network. # Bridged networks make the machine appear as another physical device on # your network. # config.vm.network "public_network" config.vm.network "public_network", ip: "192.168.135.227" # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third # argument is a set of non-required options. # config.vm.synced_folder "../data", "/vagrant_data" # Provider-specific configuration so you can fine-tune various # backing providers for Vagrant. These expose provider-specific options. # Example for VirtualBox: # config.vm.provider "virtualbox" do |vb| # Display the VirtualBox GUI when booting the machine vb.gui = false # Customize the amount of memory on the VM: vb.memory = "4096" end # # View the documentation for the provider you are using for more # information on available options. # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies # such as FTP and Heroku are also available. See the documentation at # https://docs.vagrantup.com/v2/push/atlas.html for more information. # config.push.define "atlas" do |push| # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" # end # Enable provisioning with a shell script. Additional provisioners such as # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the # documentation for more information about their specific syntax and use. # config.vm.provision "shell", inline: <<-SHELL # apt-get update # apt-get install -y apache2 # SHELL FUNCTION_INSTALL =<<EOS function install { echo installing $1 shift yum -y install "$@" >/dev/null 2>&1 } EOS # development tools etc... config.vm.provision "shell", privileged: true, inline: <<-SHELL #{FUNCTION_INSTALL} yum -y update >/dev/null 2>&1 install "development tools" gcc-c++ glibc-headers openssl-devel readline libyaml-devel readline-devel zlib zlib-devel install "Git" git install "sqlite" sqlite sqlite-devel install "Nokogiri dependencies" libxml2 libxslt libxml2-devel libxslt-devel install "ImageMagick" ImageMagick ImageMagick-devel install "vim" vim-common vim-enhanced cp /etc/localtime /etc/localtime.org ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime echo "ZONE=\"Asia/Tokyo\"" > /etc/sysconfig/clock service crond restart SHELL # MySQL5.6 config.vm.provision "shell", privileged: true, inline: <<-SHELL #{FUNCTION_INSTALL} yum install -y http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm >/dev/null 2>&1 install "MySQL" mysql mysql-server mysql-devel chkconfig --add mysqld chkconfig --level 345 mysqld on echo "Start and Initialize MySQL" service mysqld start >/dev/null 2>&1 mysql -uroot <<SQL -- SET ROOT PASSWORD -- UPDATE mysql.user SET Password=PASSWORD('vagrant') WHERE User='root'; -- REMOVE ANONYMOUS USERS -- DELETE FROM mysql.user WHERE User=''; -- REMOVE REMOTE ROOT -- DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); -- REMOVE TEST DATABASE -- DROP DATABASE IF EXISTS test; DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; -- RELOAD PRIVILEGE TABLES -- FLUSH PRIVILEGES; CREATE USER 'vagrant'@'localhost'; SET PASSWORD FOR 'vagrant'@'localhost' = PASSWORD('vagrant'); GRANT ALL PRIVILEGES ON *.* to 'vagrant'@'localhost'; SQL SHELL # memcached config.vm.provision "shell", privileged: true, inline: <<-SHELL #{FUNCTION_INSTALL} install "memcached" memcached memcached-devel chkconfig --add memcached chkconfig --level 345 memcached on echo "Start and Initialize memcached" service memcached start >/dev/null 2>&1 SHELL # rbenv config.vm.provision "shell", privileged: false, inline: <<-SHELL echo installing rbenv git clone https://github.com/sstephenson/rbenv.git ~/.rbenv git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bash_profile echo 'gem: --no-ri --no-rdoc' >> ~/.gemrc echo installing ruby#{GUEST_RUBY_VERSION} rbenv install #{GUEST_RUBY_VERSION} rbenv global #{GUEST_RUBY_VERSION} echo installing Bundler gem install bundler -N >/dev/null 2>&1 echo installing ruby-gemset cd ~/.rbenv/plugins/ git clone https://github.com/jf/rbenv-gemset.git SHELL # ntp config.vm.provision "shell", privileged: true, inline: <<-SHELL #{FUNCTION_INSTALL} install "ntp" ntp chkconfig ntpd on echo "Start and Initialize ntp" service ntpd start >/dev/null 2>&1 SHELL end
Vagrentの基本的な使い方メモ
準備
1.仮想化支援機構の有効化
2.VirtualBoxのインストール
3.Vagrantのインストール
4.CentOSのVirtualBoxへの登録
# 例 vagrant box add CentOS_6_3 https://dl.dropbox.com/sh/9rldlpj3cmdtntc/chqwU6EYaZ/centos-63-32bit-puppet.box
※公開box: http://www.vagrantbox.es/
5.Vagrant初期設定
> mkdir -p ~/Vagrant/centos6 > cd ~/Vagrent/centos6 > vagrant init CentOS_6_3 > ls # Vagrantfileファイルが存在することを確認
テキストエディタでVagrantfileを編集する。
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # Authentication failure. Retrying が出るときはパスワード指定 config.ssh.username = "vagrant" config.ssh.password = "vagrant" config.vm.box = "CentOS_6_3" #コメントアウトを外す config.vm.network "private_network", ip: "192.168.33.10" end
Vagrantコマンド
# CentOS起動 vagrant up # CentOS停止 vagrant halt # サーバ廃棄 vagrant destroy # boxファイルを作る vagrant package # ローカルのboxファイルを登録する vagrant box add MyOS package.box
その他メモ
boxファイルの保存場所
Mac /Users/<username>/.vagrant.d/boxes/ Windows C:\Users\<username>\.vagrant.d\boxes\
日本語ドキュメント
http://lab.raqda.com/vagrant/index.html
Windows上でVirtualBox+Vagrant+CentOSによる仮想環境構築
http://qiita.com/hiroyasu55/items/11a4c996b0c62450940f
MySQLにblobで格納されたデータをまとめてファイル出力する
旧システムから新システムへのデータ移行の現場での一コマ。
DBにblobで格納されてた画像データをまとめてファイル出力したかったので、
PHPスクリプトを書いてみた。
<?php // DB接続情報 $db_host = 'localhost'; $db_user = 'root'; $db_pass = 'hogehoge01'; $db_name = 'db_name'; // 対象テーブルリスト $tables = array( 'a_images', 'b_images', 'c_images', 'd_images', 'e_images', 'f_images', ); $db = mysql_connect($db_host, $db_user, $db_pass); if ($db == false) { echo "database connect error\n"; exit; } echo "database connect\n"; if (!mysql_select_db($db_name, $db)) { echo "database $db_name is not exist\n"; exit; } echo "selcted database $db_name\n"; foreach ($tables as $table) { $sql = "SELECT * FROM $table"; $result = mysql_query($sql); while ($row = mysql_fetch_array($result)) { // ファイル出力先ディレクトリ $dir_path = 'files' . '/' . $table . '/' . $row['id']; mkdir($dir_path, 0777, true); // ファイル名はfilename, // バイナリはdataカラムに格納されている前提 $file_path = $dir_path . '/' . $row['filename']; $fp = fopen($file_path, 'w'); fwrite($fp, $row['data']); fclose($fp); echo 'File output from ' . $table . '(id = ' . $row['id'] . ")\n"; } }
シェルでカレントディレクトリ配下のテキストファイルの中身を一斉置換
よく忘れるのでメモ。
# カレントディレクトリ以下 hoge を含むファイルを確認 grep -rn "hoge/" ./. # hoge を fuga に一斉置換 grep -rl "hoge" ./. | xargs sed -i -e "s/hoge/fuga/g" ${1} # コピペ用 FROM=hoge TO=fuga grep -rl "${FROM}" ./. | xargs gsed -i -e "s/${FROM}/${TO}/g" ${1} # 特定のディレクトリを除外 grep -rl --exclude-dir=.git "${FROM}" ./. | xargs gsed -i -e "s/${FROM}/${TO}/g" ${1}
VirtualBoxのゲストOS(CentOS)に複数の固定IPを設定する
表題の件の作業メモです。
ネットワークの割当は[ブリッジアダプター]を想定。
作業前:
eth8 に 192.168.135.224 を割り当て
作業後:
eth8 に 192.168.135.224 を割当
eth9 に 192.168.135.225 を割当
アダプターを増やす
VirtualBoxの設定 > ネットワーク でアダプター2を有効化。
それぞれ割当を[ブリッジアダプター]にします。
次にCentOSを起動しrootでログインし、
ifconfigでネットワークアダプタが増えていることを確認します。
eth8 Link encap:Ethernet HWaddr 08:00:27:9F:8E:30 inet addr:192.168.135.224 Bcast:192.168.135.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe9f:8e30/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2466 errors:0 dropped:0 overruns:0 frame:0 TX packets:467 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:232580 (227.1 KiB) TX bytes:62891 (61.4 KiB) eth9 Link encap:Ethernet HWaddr 08:00:27:5C:87:BF inet addr:192.168.135.71 Bcast:192.168.135.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe5c:87bf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2185 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:218982 (213.8 KiB) TX bytes:1152 (1.1 KiB)
増やしたアダプターにIPアドレスを割当
既に存在するeth8の設定をコピーします。
# cd /etc/sysconfig/network-scripts/ # cp ifcfg-eth8 ifcfg-eth9
ifcfg-eth9を編集します。
TYPE=Ethernet BOOTPROTO=none IPADDR=192.168.135.225 # IPアドレス書き換え PREFIX=24 GATEWAY=192.168.135.1 DNS1=192.168.135.1 DEFROUTE=yes IPV4_FAILURE_FATAL=yes IPV6INIT=no NAME="eth9" # 名前変える UUID=ecc2e8f6-81b0-4e04-ae26-6ece18645648 # UUIDは下一桁を1ずらすなど別の値に調整 ONBOOT=yes HWADDR=08:00:27:5C:87:BF # VirtualBox > 設定 > ネットワーク > アダプター2 で確認できる MACアドレスを記載 LAST_CONNECT=1426591352
設定を反映
下記コマンドで設定を反映します。
# service network restart インターフェース eth8 を終了中: デバイスの状態: 3 (切断済み) [ OK ] インターフェース eth9 を終了中: デバイスの状態: 3 (切断済み) [ OK ] ループバックインターフェースを終了中 [ OK ] ループバックインターフェイスを呼び込み中 [ OK ] インターフェース eth8 を活性化中: アクティブ接続の状態: アクティベート済み アクティブ接続のパス: /org/freedesktop/NetworkManager/ActiveConnection/3 [ OK ] インターフェース eth9 を活性化中: アクティブ接続の状態: アクティベート済み アクティブ接続のパス: /org/freedesktop/NetworkManager/ActiveConnection/4 [ OK ]
確認
ifconfigで設定が反映されていることを確認しておわり。
# ifconfig eth8 Link encap:Ethernet HWaddr 08:00:27:9F:8E:30 inet addr:192.168.135.224 Bcast:192.168.135.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe9f:8e30/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4727 errors:0 dropped:0 overruns:0 frame:0 TX packets:1167 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:431732 (421.6 KiB) TX bytes:164535 (160.6 KiB) eth9 Link encap:Ethernet HWaddr 08:00:27:5C:87:BF inet addr:192.168.135.225 Bcast:192.168.135.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe5c:87bf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3529 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:349928 (341.7 KiB) TX bytes:1152 (1.1 KiB)
UPDATE文でLEFT JOIN
SQL力が不足していて、LEFT JOINしたテーブルの値でUPDATEしたいときのやり方がわからなかったのでメモ。
# 確認用 SELECT * FROM users LEFT JOIN stores ON stores.id = users.store_id WHERE stores.company_id != users.copany_id; # UPDATE文 UPDATE users lEFT JOIN stores on stores.id = users.store_id SET users.company_id = stores.company_id WHERE stores.company_id != users.copany_id;
闇が深いDB設計になっているのは気にしない。
こちら参考にさせていただきました!感謝です!
mysqlでjoinした結果をupdate - Qiita
RailsのArelの使い方
RailsでArelを使うときは、下記サイトをいつも参照させていただいていましたが、自分メモ用として転載します。
メモ || Arelのwhere系メソッド一覧 User.w...
User.where(User.arel_table[:name].eq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE "users"."name" = 'aa' User.where(User.arel_table[:name].eq(nil)).to_sql # => SELECT "users".* FROM "users" WHERE "users"."name" IS NULL User.where(User.arel_table[:name].eq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' AND "users"."name" = 'bb')) User.where(User.arel_table[:name].eq_all(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' AND "users"."name" IS NULL)) User.where(User.arel_table[:name].eq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' OR "users"."name" = 'bb')) User.where(User.arel_table[:name].eq_any(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" = 'aa' OR "users"."name" IS NULL)) User.where(User.arel_table[:name].not_eq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" != 'aa') User.where(User.arel_table[:name].not_eq(nil)).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" IS NOT NULL) User.where(User.arel_table[:name].not_eq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' AND "users"."name" != 'bb')) User.where(User.arel_table[:name].not_eq_all(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' AND "users"."name" IS NOT NULL)) User.where(User.arel_table[:name].not_eq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' OR "users"."name" != 'bb')) User.where(User.arel_table[:name].not_eq_any(["aa",nil])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" != 'aa' OR "users"."name" IS NOT NULL)) User.where(User.arel_table[:name].gt("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" > 'aa') User.where(User.arel_table[:name].gt_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" > 'aa' AND "users"."name" > 'bb')) User.where(User.arel_table[:name].gt_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" > 'aa' OR "users"."name" > 'bb')) User.where(User.arel_table[:name].gteq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" >= 'aa') User.where(User.arel_table[:name].gteq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" >= 'aa' AND "users"."name" >= 'bb')) User.where(User.arel_table[:name].gteq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" >= 'aa' OR "users"."name" >= 'bb')) User.where(User.arel_table[:name].lt("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" < 'aa') User.where(User.arel_table[:name].lt_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" < 'aa' AND "users"."name" < 'bb')) User.where(User.arel_table[:name].lt_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" < 'aa' OR "users"."name" < 'bb')) User.where(User.arel_table[:name].lteq("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" <= 'aa') User.where(User.arel_table[:name].lteq_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" <= 'aa' AND "users"."name" <= 'bb')) User.where(User.arel_table[:name].lteq_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" <= 'aa' OR "users"."name" <= 'bb')) User.where(User.arel_table[:name].in(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE "users"."name" IN ('aa', 'bb') User.where(User.arel_table[:birthday].in('1980-01-01'.to_date..'1990-12-31'.to_date)).to_sql # => SELECT "users".* FROM "users" WHERE "users"."birthday" BETWEEN '1980-01-01' AND '1990-12-31' User.where(User.arel_table[:name].in_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" IN ('aa') AND "users"."name" IN ('bb'))) User.where(User.arel_table[:name].in_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" IN ('aa') OR "users"."name" IN ('bb'))) User.where(User.arel_table[:name].not_in(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" NOT IN ('aa', 'bb')) User.where(User.arel_table[:name].not_in_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT IN ('aa') AND "users"."name" NOT IN ('bb'))) User.where(User.arel_table[:name].not_in_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT IN ('aa') OR "users"."name" NOT IN ('bb'))) User.where(User.arel_table[:name].matches("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" LIKE 'aa') User.where(User.arel_table[:name].matches("%aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" LIKE '%aa') User.where(User.arel_table[:name].matches_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" LIKE 'aa' AND "users"."name" LIKE 'bb')) User.where(User.arel_table[:name].matches_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" LIKE 'aa' OR "users"."name" LIKE 'bb')) User.where(User.arel_table[:name].does_not_match("aa")).to_sql # => SELECT "users".* FROM "users" WHERE ("users"."name" NOT LIKE 'aa') User.where(User.arel_table[:name].does_not_match_all(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT LIKE 'aa' AND "users"."name" NOT LIKE 'bb')) User.where(User.arel_table[:name].does_not_match_any(["aa","bb"])).to_sql # => SELECT "users".* FROM "users" WHERE (("users"."name" NOT LIKE 'aa' OR "users"."name" NOT LIKE 'bb'))