サービスを停止せずにログローテーション(logrotate)を行う


さくらVPSにて行った設定。
サーバー設定に関しては素人の域を出ておらず、今回行った設定についても改善点は多いかとは思いますが、備忘録として残しておきます。
(もしかしたら解釈が間違っているものもあるかもしれません)

logrotate の設定

vim /etc/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
#weekly
daily

# keep 4 weeks worth of backlogs
#rotate 4
rotate 7

logrotate の実行を週1(weekly)から、毎日(daily)に変更。
ログを残すのは4世代分から7世代分に変更。

HTTPデーモンのログローテーション設定

vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
    missingok
    notifempty
    sharedscripts
#    delaycompress
    postrotate
#        /sbin/service httpd reload > /dev/null 2>/dev/null || true
        /sbin/service httpd graceful > /dev/null 2>/dev/null || true
    endscript
}

「delaycompress」は、設定ファイル(/etc/logrotate.conf)で圧縮をかけない設定になっているためコメントアウト。
圧縮する設定になってないと無視されますが、不必要ならコメントアウトするか削除しておかないと、他の人がみたときに「圧縮処理をかけたいのに設定ファイルを書き換え忘れている」のか「無視されるから残している」のか判断がつき辛いですからね。
で、削除するとログの容量が増えてきて圧縮が必要になった時に戻すのが面倒なので、コメントアウトにしています。

「httpd reload」となっていたところを、「httpd graceful」に変更。
これにより、稼働中のプロセスは終了することなく、再起動の処理が行われる。
logrotate 実行時に稼働中だったプロセスは、そのまま旧ファイルにログが書き込まれる。

PHPのログローテーション設定

vim /etc/logrotate.d/php
/var/log/php/php_errors.log {
    missingok
    notifempty
    delaycompress
    copytruncate
}

先ほどの「httpd」のローテートとは違い、こちらでは「copytruncate」を使用してログファイルのローテーションをさせています。
「copytruncate」では、現在のログファイルをコピーして旧世代のファイルを作成しています。
その後現在のログファイルの中身を消去することで、再起動処理を必要とすることなくログのローテーションを可能としています。
ただしこの方法では、「ファイルコピー ~ 中身の消去」の間に発生したログは、どちらのファイルにも残らないという欠点があります。

PHPのログはそこまでの精度を求めていないのと、「httpd graceful」を行うよりサーバーへの負担が軽いのかな?と思って「copytruncate」にしていますが、もしかしたら両方「httpd graceful」でやった方が良いのかもしれません。
この辺の知識がまだまだ足りてないため、現在はこの設定にしています。
もう少し詳しくなったら、また設定を変えるかもしれません。

ディレクティブ説明

missingok 指定のログファイルが実在しなかったとしてもエラーを出さずに処理続行
notifempty 元のログファイルが空ならばローテーションしない
sharedscripts ローテーションの条件に合致するログが複数あった場合に、prerotate, postrotate のスクリプトを一度だけ実行する
delaycompress 圧縮処理を、その次のローテーションの時まで遅らせる。compress も指定しないと無意味
postrotate

endscript
実際にローテーションが行われた後 (lastaction よりは前) に実行するスクリプト。
copytruncate copy の動作を行った後、内容を消去する。これはログファイルをリロードする術のないプログラムへの対処法のひとつ。

参考サイト
Stray Penguin – Linux Memo (logrotate)

デバッグ

# 全テスト
logrotate -dv /etc/logrotate.conf

# 個別にテスト
logrotate -dv /etc/logrotate.d/httpd

「-d」でデバッグモード、「v」をつけると詳細表示。

実行ログの確認

less /var/lib/logrotate.status

 


【jQuery】textareaの入力内容を簡単にHTML↔テキスト切り替え


メール配信システム作成にあたり、入力結果プレビューを簡単に実装できないかと色々調べた結果、jQueryを利用すれば簡単にプレビューを表示することができました。

jQueryを利用すれば、テキストメールとHTMLメールのプレビューも簡単に切り替えることができます。

まずは、サンプルをどうぞ。
【jQuery】textareaの入力内容を簡単にHTML↔テキスト切り替え|サンプル

主な記述は下記のみで、実装できます。

<script>
$(function() {
  $('textarea[name="body"]').keyup(function() {
    if($('input[name="sort"]:checked').val() == 'html') {$('#preview_body').html($('textarea[name="body"]').val());}
    else {$('#preview_body').text($('textarea[name="body"]').val());}
  });
  $('input[name="sort"]').click(function() {
    if($('input[name="sort"]:checked').val() == 'html') {$('#preview_body').html($('textarea[name="body"]').val());}
    else {$('#preview_body').text($('textarea[name="body"]').val());}
  });
});
</script>
<table>
	<tr>
		<th>タイプ</th>
		<td>
			<label><input type="radio" name="sort" value="text">テキスト</label>
			<label><input type="radio" name="sort" value="html">HTML</label>
		</td>
	</tr>
	<tr>
		<th>本文</th>
		<td>
			<textarea name="body" cols="40" rows="20"></textarea>
		</td>
	</tr>
</table>
<div>
	<h2>本文プレビュー</h2>
	<div id="preview_body"></div>
</div>

3~6行目で textarea タグで keyup イベントが発生した際の処理を行っています。
7~10行目で input タグで click イベントが発生した際の処理を行っています。

keyup イベントの処理

$('textarea[name="body"]').keyup(function()

name 属性が body の textareaタグ で keyup イベントが発生したら { } 内の処理を行います。
keyup イベントは、キーボードのキーが押した後、離された際に呼び出されます。

4行目と5行目は、ちょっと長いので分解して説明します。

if($('input[name="sort"]:checked').val() == 'html')

まず if 文は、name 属性が sort になっている inputタグ の checked されている値(value)が html ならば { } 内の処理を行います。

$('#preview_body').html($('textarea[name="body"]').val());

id要素 が preview_body となっている HTML タグの中身を、jQuery の html 関数を使って texterea に入力されている内容に書き換えます。
html 関数は、入力されている内容を HTML として扱い出力します。

else

else は、4行目の if 文の条件に当てはまらなかった場合に { } 内の処理を行います。
(inputタグ の checked されている値(value)が html 以外の場合ですね)

$('#preview_body').text($('textarea[name="body"]').val());

id要素 が preview_body となっている HTML タグの中身を、jQuery の text 関数を使って texterea に入力されている内容に書き換えます。
text 関数は、入力されている内容を テキストとして扱い出力します。
< や > がエスケープされて、HTMLエンティティとして出力されます。

click イベントの処理

$('input[name="sort"]').click(function()

name 属性が sort の inputタグ で click イベントが発生したら { } 内の処理を行います。
click イベントは、マウスなどのポインティングデバイスでクリックされた際に呼び出されます。

8~9行目は、4~5行目と同じ処理を行っています。

もっとややこしい処理を色々入れないと、実装できないかと思ってましたがやってみると案外簡単に実装できました。
jQueryは便利な関数が色々揃ってますね。

jQueryを組む際にいつもお世話になっているサイト。
jQuery 日本語リファレンス


crontabでmysqldumpをデータベース毎に実行し毎日自動でバックアップ


データベース毎にMySQLのバックアップを自動で取るために設定した手順を書き記しておきます。

mkdir -pv /home/backup/mysql
chown -R user:user /home/backup

バックアップを保管するためのフォルダを作ります。

mkdir /home/user/cron

ユーザーフォルダに cron 設置用のディレクトリを作ります。

vim /home/user/cron/backup_mysql.sh

mysqldump を行うシェルスクリプトを作成し、下記の内容を書き込みます。

#!/bin/sh

# バックアップファイルを保存するディレクトリ
path='/home/backup/mysql'

# データベース名
db_name=("db_name_01" "db_name_02" "db_name_03")

date=`date +%y%m%d`

date_old=`date --date "7 days ago" +%y%m%d`

for i in ${db_name[@]}
do
  # mysqldump実行
  mysqldump --user=XXX --password=YYY --skip-lock-tables --no-create-db --single-transaction --databases ${i} > ${path}/${i}_${date}.sql

  # パーミッション変更
  chmod 700 ${path}/${i}_${date}.sql

  # 古いバックアップファイルを削除
  rm -f ${path}/${i}_${date_old}.sql
done

mysqldumpのオプションについては下記を参照。
mysqldump — データベースバックアッププログラム

chmod 700 /home/user/cron/backup_mysql.sh

DBのパスワードを記載しているため、パーミッションを絞る。

# 動作確認
/home/user/cron/backup_mysql.sh

# バックアップファイルが作成されているか確認
ls -l /home/backup/mysql
db_name_01_140725.sql
db_name_02_140725.sql
db_name_03_140725.sql

成功していれば、このようなファイルができる。

# crontabファイル
vi /home/user/crontab

「crontab -e」で直接編集するのは危険なため、crontabファイルを作成してそこに下記の内容を書き込む。

# MySQLダンプ
2 3 * * * /home/user/cron/backup_mysql.sh

毎日03:02に実行する。

crontab /home/user/crontab

crontabファイルを反映させる。

crontab -l

反映されていることを確認する。

less /var/log/cron

crontabの実行ログ確認。
※環境により、実行ログの保存ディレクトリは異なります。

mysql -u user -p db_name < /home/backup/mysql/file_name.sql

リストアが必要になった場合はこちら。

参考にしたサイト
mysqldumpとcronでMySQLを自動バックアップする