ztbuz@dev

人生に絶望しているZが、それでも技術を身につけようと必死になるブログ

Linuxでlsの実行結果をawkで取得する方法

ls -lなどで特定のファイルやディレクトリの所有者やグループなどを取得したいときがあります。 たとえば、rbenvディレクトリをls -ldすると、次のように表示されます。

$ ls -ld /usr/local/rbenv
drwxrwxr-x 10 root rbenv 4096 12月 14 17:40 2013 /usr/local/rbenv/

で、たとえば外部のプログラムから「グループがrbenvなのかどうかしりたい!」という状況を考えます。 上の例だと、たとえばgrep rbenvしても、パスの方が引っかかるため、ただしく取得できません。

このやり方について書いてみます。

特定のカラムを取得する

グループなど、特定のカラムを取得する方法として、awkをつかう方法があります。 以下は、lsした結果の4番目(グループ)を取得する例です。

$ ls -ld /usr/local/rbenv | awk '{ print $4 }'

この実行結果はrbenvとなります。

グループが特定のものかどうか判断する

上の例で、rbenvだったらそれを返し、違ったら空を返す、という例を以下に示します。 これは上を単にgrepすればよいです。

$ ls -ld /usr/local/rbenv | awk '{ print $4 }' | grep rbenv

Chef SoloでExecute Resourceをつかうときのnot_ifなどでこれが結構役に立ってきます。 このやり方がうまいやり方かどうか正直分かりませんがOnz

Linuxで環境変数のパスを確認する方法

環境構築時につかったのでメモ。

Linuxで、環境変数のパスはecho $PATHにより確認できます。 これは:により区切られていて、左の方が優先されます

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/vagrant/bin

コマンドをインストールしたのにちゃんと反映できていないときなど、パスを確認すると解決するかもしせませんね(自戒)。

こういう基本的なところからちゃんと使いこなせるようにならないとな〜、と途方にくれています。 おわり。

参考記事

Linuxでコマンドの場所を探すにはwhichコマンドを使う

とある問題を解決しているときに使ったのでメモ。

たとえばrubyコマンドの場所を探すには、以下のようにwhichコマンドをつかいます。

$ which ruby
/usr/bin/ruby

コマンドの場所を探したり、コマンドにパスがとおっているか確認するときなど、いろんなときにつかえて便利です。 おわり。

参考記事

rbenv環境下でbundle installしたときにRubyのバージョンがおかしい場合の対処例

足かけ2日ハマり、最後はstackoverflowでロシア人の方に丁寧に手ほどきされながら解決を迎えることができました。

問題の発端

Rails環境を構築していて、試しにbundle installを実行すると、以下のようなメッセージが表示されました。

Your Ruby version is 1.8.7, but your Gemfile specified 2.0.0

え、でもrbenvでちゃんとインストールしたしぃ……と思い、ruby -vを実行すると、やっぱりちゃんとインストールされてる。 どや。

$ ruby -v
ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]

ちなみに、Rubyのシステムのデフォルトは以下のとおり。

$ sudo ruby -v
ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux]

なので、早い段階でbundle installがシステムのデフォルトを参照してるのでは? というあたりはついていました。

解決策

bundleが参照しているrubyを調べてみる

とりあえずbundlerbenvじゃなくてシステムのRubyを参照していると思ったので、whichで調べてみることに。

$ which bundle
/usr/bin/bundle

なるほど、bundleはここにあるんですね。

/usr/bin/bundleをcatしてみる

で、次にこれをcatしてみました。 すると、1行目にこうありました。

#!/usr/bin/ruby

これはシステムのデフォルトを参照してますよ、ということですね。 なので、これをとりあえず以下に変えてみました(対処が適当すぎる)。

#!/usr/local/rbenv/shims/ruby

もちろんうまくいかず。

bundleの場所を疑う

で、いろいろ調べるうちに「bundlegemでインストールしたんだから、rbenv下にインストールされるはずでは?」「もしかしたらbundle自体がうまくインストールされてないんじゃ……」と思い、調べてみることに。

$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.0)
io-console (0.4.2)
json (1.7.7)
minitest (4.3.2)
psych (2.0.0)
rake (0.9.6)
rdoc (4.0.0)
test-unit (2.0.0.0)

……。 bundlerがない!

試しにシステムのデフォルトを見てみると、もちろんbundlerはありました。

$ sudo gem list

*** LOCAL GEMS ***

bundler (1.3.5)
json (1.5.5)

bundleを入れなおす

ということなので、改めてbundlerを入れなおします。

$ su
$ gem install bundler
$ rbenv rehash

で、gem listをしてみると、

$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.0)
bundler (1.3.5)
io-console (0.4.2)
json (1.7.7)
minitest (4.3.2)
psych (2.0.0)
rake (0.9.6)
rdoc (4.0.0)
test-unit (2.0.0.0)

あったー!

which bundleしてみると、

$ which bundle
/usr/local/rbenv/shims/bundle

はいったー!

bundle installしてみると、

$ bundle install

(省略)

できたー! おしまい。

補足:なぜシステムの方が使われた?

環境設定のパスを見てみると、次のようになってます。

$ echo $PATH
/usr/local/rbenv/shims:/usr/local/rbenv/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/vagrant/bin

これは左から優先順に適用されます。 つまり、rbenv/shims下になかったので、usr/bin/下のbundleが実行されていたのですね。

とりあえず、なんでChef Soloでレシピを書いているにも関わらずbundlerが入らなかったのか、今から調査します。。。

Chef SoloでVagrant上にMySQLをインストールする方法

つぎはChef SoloでVagrant上にMySQLをインストールしてみます。 すこし手間取りましたが、思ったよりすんなりいきました。

MySQLをインストールする準備

クックブックを作成する

おなじみクックブックを作成します。 名前はmysqlにします。

$ knife cookbook create mysql -o site-cookbooks/

rpmファイルをダウンロードする

MySQLの公式サイトから、rpmファイルをダウンロードしてきます。

今回ダウンロードするものは以下のとおりです。

ダウンロードしたものは、site-cookbooks/mysql/files/default/下に配置します。

レシピを編集する

mysql-libsを削除する

MySQL Serverのインストールを試みると、以下のようなエラーが起きました。

ファイル /usr/share/mysql/czech/errmsg.sys (パッケージ MySQL-server-5.6.15-1.el6.x86_64 から) は、パッケージ mysql-libs-5.1.66-2.el6_3.x86_64 からのファイルと競合しています。

いろいろ調べてみると、どうやら標準で入っているmysql-libsと競合しているようです。

これを消しても、MySQL-shared-compat.rpmを入れれば問題ないようなので、サクッと消します。

$ vi site-cookbooks/mysql/recipes/default.rb

package 'mysql-libs' do
  action :remove
end

/tmp/にrpmをつくる

つぎに、ダウンロードしたMySQLの各ファイルをノード側に配置します。 これはdefault.rbに以下のように書きます。

cookbook_file '/tmp/MySQL-server.rpm' do
  source 'MySQL-server-5.6.15-1.el6.x86_64.rpm'
end

cookbook_file '/tmp/MySQL-client.rpm' do
  source 'MySQL-client-5.6.15-1.el6.x86_64.rpm'
end

cookbook_file '/tmp/MySQL-devel.rpm' do
  source 'MySQL-devel-5.6.15-1.el6.x86_64.rpm'
end

cookbook_file '/tmp/MySQL-shared.rpm' do
  source 'MySQL-shared-5.6.15-1.el6.x86_64.rpm'
end

cookbook_file '/tmp/MySQL-shared-compat.rpm' do
  source 'MySQL-shared-compat-5.6.15-1.el6.x86_64.rpm'
end

インストールする

あとはrpmからインストールするだけです。 これもdefault.rbに書いていきます。

rpm_package 'MySQL-server' do
  source '/tmp/MySQL-server.rpm'
end

rpm_package 'MySQL-client' do
  source '/tmp/MySQL-client.rpm'
end

rpm_package 'MySQL-devel' do
  source '/tmp/MySQL-devel.rpm'
end

rpm_package 'MySQL-shared' do
  source '/tmp/MySQL-shared.rpm'
end

rpm_package 'MySQL-shared-compat' do
  source '/tmp/MySQL-shared-compat.rpm'
end

実行する

華麗に実行します。

$ knife solo cook sample

で、で、できたー!(できなかったらごめんなさい)

参考サイト

追記:2013/12/15

以下のように、もっとすっきりと書いてみました。

レシピ

$ vi site-cookbooks/mysql/recipes/default.rb

package 'mysql-libs' do
  action :remove
end

node['mysql']['rpm'].each do |rpm|
  cookbook_file "/tmp/#{rpm}" do
    action :create
    source "#{rpm}"
  end

  rpm_package "#{rpm}" do
    action :install
    source "/tmp/#{rpm}"
  end
end

rpmの設定

$ vi site-cookbooks/mysql/attributes/default.rb

default['mysql']['rpm'] = [
  'MySQL-server-5.6.15-1.el6.x86_64.rpm',
  'MySQL-client-5.6.15-1.el6.x86_64.rpm',
  'MySQL-devel-5.6.15-1.el6.x86_64.rpm',
  'MySQL-shared-5.6.15-1.el6.x86_64.rpm',
  'MySQL-shared-compat-5.6.15-1.el6.x86_64.rpm'
]

Chef SoloでVagrant上にRubyをインストールする方法

ChefでVagrant上にrubyの実行環境を構築してみましたので、そのレシピを公開などしてみます。

ただ、基本的に以下の記事と同じような形になってしまいますた。。。

クックブックの内容

レシピを作成する

まずはサクッとレシピを作成しましょう。 名前はrubyにします。

$ knife cookbook create ruby -o site-cookbooks/

rbenvを準備する

rubyをインストールするには、まずrbenvをインストールします。 1ブロックずつ書いてcookしていけば、動きが分かってよいです。

$ vi /site-cookbooks/ruby/recipes/rbenv.rb

group 'rbenv' do
  action :create
  members 'vagrant'
  append true
end

git '/usr/local/rbenv' do
  repository 'git://github.com/sstephenson/rbenv.git'
  reference 'master'
  action :checkout
  user "#{node.user}"
  group 'rbenv'
end

directory '/usr/local/rbenv/plugins' do
  action :create
  owner "#{node.user}"
  group 'rbenv'
  mode 0755
end

template '/etc/profile.d/rbenv.sh' do
  owner "#{node.user}"
  group "#{node.user}"
  mode 0644
end

PackageやDSLが分からなくなったら、とりあえず公式ドキュメントを見ます!

ruby-buildを準備する

次にruby-buildをインストールします。 これはgitから持ってくるだけです。

$ vi /site-cookbooks/ruby/recipes/ruby-build.rb

git '/usr/local/rbenv/plugins/ruby-build' do
  repository 'git://github.com/sstephenson/ruby-build.git'
  reference 'master'
  action :checkout
  user "#{node.user}"
  group 'rbenv'
end

インストールする

あとは上記をinstallでインストールして、globalでバージョンを切り替えるだけです。

$ vi /site-cookbooks/ruby/recipes/install.rb

execute 'ruby install' do
  not_if "source /etc/profile.d/rbenv.sh; rbenv versions | grep #{node.ruby.version}"
  command "source /etc/profile.d/rbenv.sh; rbenv install #{node.ruby.version}"
  action :run
end

execute 'ruby change' do
  command "source /etc/profile.d/rbenv.sh; rbenv global #{node.ruby.version}; rbenv rehash"
  action :run
end

default.rbから呼び出す

上記の手順を明示的に実行するため、include_recipeを書きます。

$ vi /site-cookbooks/ruby/recipes/default.rb

include_recipe 'ruby::rbenv'
include_recipe 'ruby::ruby-build'
include_recipe 'ruby::install'

環境設定を書く

上記ファイルに#{node.user}#{node.ruby.version}といった変数があると思います。 これも設定します。

$ vi /site-cookbooks/ruby/attributes/default.rb

default['user'] = 'root'
default['ruby']['version'] = '2.0.0-p353'

実行

あとはnodes/[host].jsonrun_listに追記して、knife solo cookすればrubyのインストールが完了します! だいぶレシピの書き方が分かってきた……ような、気が、するだけ、ですね。。。

ファイルのパーミッションの"T"はスティッキービットというらしい

Chefでrbenvbashを作成したところ、ファイルのパーミッションが以下のようになりました。

--w----r-T   1 root root   93 12月 12 11:00 2013 rbenv.sh

原因は、mode0644ではなく644とタイポしたというだけのことですが、このTとはなんぞ? と思ったので、調べてみました。

Tはスティッキー・ビット

どうやらパーミッションには、rwx以外にもTやらなにやらがあるらしいのです。 Tは、スティッキービットと呼ばれ、以下のような特徴があるらしいです。

スティッキービットの最も一般的な使用法は、ディレクトリに対して使う場合であり、セットされるとディレクトリ配下のファイルのファイル名変更や削除はそのファイルの所有者、ディレクトリの所有者、スーパーユーザーのいずれかしかできなくなる。

ふむふむ。

スティッキービットの設定方法

じゃあどうやったらスティッキービットを設定するの、という話ですが、以下の方法で設定できるようです。

chmod 1777 hoge

chmodにこんな裏要素があるなんて知りませんでした。。。