2015年3月21日土曜日

「PHP Warning: Module 'PDO' already loaded in Unknown on line 0」が発生したら

/etc/php.iniの設定がミスっているようです。

pdoのモジュールを複数読み込みさせていると、下記のWarningメッセージが発生するようです。
PHP Warning: Module 'PDO' already loaded in Unknown on line 0

対応方法としては、php.iniのpdoの読み込みを1つにすれば良いようです。

修正前
extension=pdo.so
extension=pdo_mysqlnd.so

修正後
;extension=pdo.so
extension=pdo_mysqlnd.so

※参考URL
原因
https://www.extendwings.com/blog/2013/03/php-output-warning/

解決方法
http://ora.geo.jp/?p=538

2015年3月19日木曜日

sftpの権限だけのユーザを作成する(ディレクトリの制限も)

今回満たしたい要件は下記です
・ssh接続をさせない
・sftp接続は可能
・サーバ内のとあるディレクトリ配下しか利用させない。閲覧もさせたくない。
・umask 002でファイル配置
・ログインはパスワード(鍵ファイルではない)


・まずはユーザを作成します

adduser sftp-user -g www

※-g www はグループを指定しています。
(これは通常のユーザと同じにしてあります。そうすることにより、sftp-userが配置したファイルを通常ユーザが利用できる状態になります。(umask 002の設定しているので))

passwd sftp-user


・それでは、実際に今回の要件を満たす設定をしていきます。
修正するファイルは下記のみです。
/etc/ssh/sshd_config

○sshd_config 1カ所目
Subsystem sftpと記載のある箇所をかきの様に書き換えます。

Subsystem sftp /usr/libexec/openssh/sftp-server

Subsystem sftp internal-sftp -u 002

sftp-serverからinternal-sftpへの変更は、ディレクトリ制限をする都合上こちらのほうが都合がいいという理由です。
-u 002はumask 002という意味になります。
これで、sftpで作成されたファイルはumask 002の状態となります。

○sshd_config 2カ所目
ファイルの最終行に下記を追加してください。

Match User sftp-user
PasswordAuthentication yes
PubkeyAuthentication no
RSAAuthentication no
ChrootDirectory /home/neostage
ForceCommand internal-sftp -u 002


解説
・Subsystem sftp internal-sftp
これは、sftpでディレクトリ制限を付与するときにstfp-serverよりも楽に設定ができる記述のようです。
・Match User ユーザ名
これ以降の設定は、指定したユーザのみ適応されるという記述になります。
・PasswordAuthentication yes
パスワード認証にする
・PubkeyAuthentication no
公開鍵認証しない
・RSAAuthentication no
RSA認証しない
・ChrootDirectory
sftpの際のrootディレクトリとなる。これ以降のディレクトリしか操作出来ない
・ForceCommand internal-sftp -u 002
sftpにinternal-sftpを利用し、umaskを002設定する

上記設定後にsshdを再起動します。
/etc/rc.d/init.d/sshd restart

※再起動時には絶対に接続中の端末はログアウトしないでください。
再起動後は、別のターミナルで接続確認を行い、問題ないことを確認してください。
そうしないと、一生SSHでログインできない環境が出来上がってしまいます!


★上記設定のハマりポイント!
ChrootDirectory で指定しているディレクトリのPermissionには気をつけてください。
必ず、所有者はroot、グループもroot、権限は755で作成してください。
ChrootDirectory で指定している全ての階層のディレクトリが対象です。これをやらないとsftpが使えません!

2014年9月23日火曜日

Ruby on Rails4 で バッチ処理をする(rails runner, whenever)

railsのコマンドでrunnerというコマンドがある
例)
rails runner Tasks::AlertTask.execute
これを利用します。

crontabへの登録はcrontab -eで手書きすることもできるが、モジュール管理もできるのでrubyで書く方法をためします。

・バッチモジュール作成
> vim config/application.rb
config.autoload_paths += %W(#{config.root}/lib) # 追記する
バッチクラス作成
> vim lib/tasks/alert_task.rb
class Tasks::AlertTask

  def self.execute
    puts "Hoge"
  end
end

ちゃんと作成出来たかを確認する。
> rails runner Tasks::AlertTask.execute
Hoge

・スケジュール登録(crontabへの登録手順)
> vim Gemfile
gem 'whenever', :require => false # 追記

> bundle install

config/schedule.rbを作成
> wheneverize .

> vim config/schedule.rb

set :output, "log/cron_log.log" # ログファイルパス
set :environment, :development # 実行環境
every 1.day, :at => '5:00 am' do # 毎日5時に実行
  runner "Tasks::AlertTask.execute" # 実行するタスク(lib/tasks/alert_task.rbのexecuteメソッドを実行)
end

crontab登録
> bundle exec whenever -update-crontab

crontab確認
> crontab -l

もし、実行されなかった場合。
パターン1:
bin/rails:7: undefined method `require_relative' for main:Object (NoMethodError)
と表示される場合はrubyが複数存在する可能性があります。下記にて不要なrubyを消しましょう。
> yum remove ruby

パターン2:
/usr/bin/env: ruby: No such file or directory
と表示される場合は下記を実施。
> vim ~/.bashrc
export PATH=/usr/local/bin:$PATH

2014年9月3日水曜日

JavaScriptで数値の桁あふれでハマった・・・

お好きなブラウザで確認できるので、一度試してみるといいかもしれません。

ブラウザの開発者ツールでコンソールを表示し、下記を入力して下さい。
var i = 1118918899790958592;

この数値がiという変数に格納されていると思いますよね。
では、そのままコンソールでiを出力してみてください。
> var i = 1118918899790958592;
> i
1118918899790958600
んっ!!!!!
ということで、10の位で丸められていますね。。。
どんな桁落ちだよ。

通常こんなでかい数字を扱うことはないと思うのですが、今回利用していたAPIの戻り値がJSONでそのID的なものが数値型でこの桁数という・・・。
やられたわー。
4時間くらい楽しんでしまった・・・。

2014年8月20日水曜日

Ruby on Rails4をproduction環境として動かす(nginx + unicorn)

rails4(nginx + unicorn)での動かし方をまとめます。

環境は下記となります。
・Ruby2.1
・nginx
・unicorn

1.Unicornをインストールする
Gemfileに書きを追記
gem 'unicorn'
追記後にbundle installをお忘れなく。

2.config/unicorn.rb作成(下記をコピペでいい)
application = '{適当なアプリ名}'

worker_processes 2
working_directory "/#{application}"

listen "/var/run/unicorn/unicorn_#{application}.sock"   # Unix Domain Socket

pid "/var/run/unicorn/unicorn_#{application}.pid"       # PIDファイル出力先
 
timeout 60
 
preload_app true

stdout_path "/var/log/unicorn/unicorn.stdout_#{application}.log"  # 標準出力ログ出力先
stderr_path "/var/log/unicorn/unicorn.stderr_#{application}.log"  # 標準エラー出力ログ出力先
 
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
 
before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
        Process.kill(sig, File.read(old_pid).to_i)
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
 
    sleep 1
  end
 
after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
3.assetsをプリコンパイルする
production環境ではassetsを毎回コンパイルすると遅いらしいので、最初にコンパイルさせる。
bundle exec rake assets:precompile
4.unicorn起動
unicorn_rails -c config/unicorn.rb -E production -D -p 13000

5.nginxの設定
/etc/nginx/conf.d/rails.conf的なファイルに書きを記載(rails.confは.confがあれば勝手に読み込むのでファイル名は何でも良い)
upstream unicorn-unix-domain-socket {
   ### unicorn.rbで指定したUnicornのソケットを指定:
   server unix:/var/run/unicorn/unicorn_subsche.sock fail_timeout=0;
}

upstream unicorn-tcp {
   ### unicornのポートを指定 ※ここでは、Unicorn起動時にポート 13000で起動させるものとします。
   server 127.0.0.1:13000;
}

server {
   listen 80;
   server_name {サーバ名};

   root /{アプリパス}/public;

   access_log  /var/log/nginx/access.log;
   error_log /var/log/nginx/error.log;

   location ^/assets/ {
       root /{アプリパス}/public;
   }


   auth_basic "user name";
   auth_basic_user_file "/etc/nginx/htpasswd";

   location / {
       if (-f $request_filename) {
           break;
       }

       proxy_set_header X-Real-IP  $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;

       proxy_pass http://unicorn-unix-domain-socket;
    }

    location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
       expires 1y;
    }
}


6.nginx起動
service nginx start
起動しているのであれば、下記コマンド。
service nginx restart

7.ブラウザからアクセス
表示できれば終わり。表示できなければ下記を確認して下さい。


■起動しない場合
・DBがない
・SECRET_KEY_BASEを設定していない

ポイント1.DBがない
ずっとdevelopment環境で開発している場合、production用のdatabaseが作成されていない可能性があります。
下記コマンドで、production用のdatabaseを作成しましょう。
rake db:create db:migrate RAILS_ENV=production

ポイント2. SECRET_KEY_BASEを設定していない
下記のエラーが出る場合は、きっとこのパターンです。
E, [2014-08-20T22:34:16.262827 #3625] ERROR -- : app error: Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml` (RuntimeError)
E, [2014-08-20T22:34:16.263001 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/railties-4.1.4/lib/rails/application.rb:452:in `validate_secret_key_config!'
E, [2014-08-20T22:34:16.263061 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/railties-4.1.4/lib/rails/application.rb:195:in `env_config'
E, [2014-08-20T22:34:16.263083 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/railties-4.1.4/lib/rails/engine.rb:510:in `call'
E, [2014-08-20T22:34:16.263103 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/railties-4.1.4/lib/rails/application.rb:144:in `call'
E, [2014-08-20T22:34:16.263122 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/unicorn-4.8.3/lib/unicorn/http_server.rb:576:in `process_client'
E, [2014-08-20T22:34:16.263142 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/unicorn-4.8.3/lib/unicorn/http_server.rb:670:in `worker_loop'
E, [2014-08-20T22:34:16.263160 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/unicorn-4.8.3/lib/unicorn/http_server.rb:525:in `spawn_missing_workers'
E, [2014-08-20T22:34:16.263187 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/unicorn-4.8.3/lib/unicorn/http_server.rb:140:in `start'
E, [2014-08-20T22:34:16.263206 #3625] ERROR -- : /usr/local/lib/ruby/gems/2.1.0/gems/unicorn-4.8.3/bin/unicorn_rails:209:in `'
E, [2014-08-20T22:34:16.263225 #3625] ERROR -- : /usr/local/bin/unicorn_rails:23:in `load'
E, [2014-08-20T22:34:16.263243 #3625] ERROR -- : /usr/local/bin/unicorn_rails:23:in `
'
config/secrets.ymlファイルで「secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>」という部分が存在するため、下記コマンドを実施する。
export SECRET_KEY_BASE=`rake secret`
その後、unicornの再起動を行う。

これでアクセス出来なければ別な問題かもしれません。