スキップしてメイン コンテンツに移動

投稿

2013の投稿を表示しています

CentOS 6.3 で確認した Apache アクセスログのローテーション設定

CentOS 6.3 でのお話。 Apacheをyumでインストールすると、Apacheログのローテート設定ファイルが作られる。 # less /etc/logrotate.d/httpd /var/log/httpd/*log { missingok notifempty sharedscripts delaycompress postrotate /sbin/service httpd reload > /dev/null 2>/dev/null || true endscript } logrotateはcronで実行されるようになっている。 # ls /etc/cron.daily logrotate このlogrotateの中身を確認すると #!/bin/sh /usr/sbin/logrotate /etc/logrotate.conf >/dev/null 2>&1 EXITVALUE=$? if [ $EXITVALUE != 0 ]; then /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]" fi exit 0 となっていて、以下の /etc/logrotate.conf の定義をもとにログをローテートしている。 # see "man logrotate" for details # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # use date as a suffix of the rotated file dateext # uncomment this if you want your log files compressed #compress # RPM packages drop log rotation infor...

apache アクセスログの圧縮

# less /etc/httpd/conf/httpd.conf CustomLog "| /usr/sbin/rotatelogs /var/log/httpd/access_log.%Y%m%d 86400 540" combined 上記のように出力されているapacheアクセスログファイルを圧縮するスクリプト #!/bin/bash LOGDATE=`date -d '1 days ago' +'%Y%m%d'` gzip /var/log/httpd/access_log.$LOGDATE このスクリプトをcronで仕込めばOK。 参考にさせてもらったところ ■15分で理解するApacheのログローテート http://wimax.blog64.fc2.com/blog-entry-91.html

Google Maps JavaScript API バージョン 2(V2) 復活!?

2013/11/20 にV2のまま放置したサイトを見てみたら、地図が出ていなかった。 そりゃね、延期された Google Maps JavaScript API バージョン 2(V2)のサポートも、2013/11/18 に終わっちゃったしね。 と思って、11/21 にV2のまま放置した同じサイトを見てみたら、 でてるやん! ということで、復活したのかなぁ

find xargs grep で、PHP のソースを検索

拡張子が .html のファイルから、PHP のソースが記述されているファイルを抽出する必要があったので、find と xargs と grep の合わせ技で検索してみた。 こんな感じ。 cd /var/www/html find . -name "*.html" -type f -print0 | xargs -0 grep -P '<\?[\s\S]*?\?>' grep の -P オプションで複数行を対象とし、 正規表現の [\s\S]*? で改行が含まれている範囲も検索している。 なぜ、拡張子が.html のファイルを対象にしているかって? それはね、.htaccess に AddType application/x-httpd-php .php .html って定義してあったサイトをバックアップから戻したときに 「サーバでPGが動くファイルは、戻さないで」 っていうオーダーがあったから。 じゃあ、なぜそんなオーダーが来たかというと...云わずもがなです。 ちなみに、 <??> で囲まれている箇所を抽出しているので、 <?xml version="1.0" encoding="UTF-8"?> みたいな XML宣言 も抽出されてしまう。

OpenIDについてぼやく

FacebookもYahooもmixiもOpenIDに対応してるって言ってるけど、肝心のOpenIDを使ってログインできるページがどこにも見当たらない。 googleアカウント持ってるから、googleのOpenID使ってログインしたいんだけど、する場所がない。 googleにもない。 俺の理解が不足しているのか、探し方が下手なのか。 そもそも、OpenIDって、サイト間でログイン情報(ID、パスワード)を共有しましょうっていうあれでしょ? Facebookアカウント持ってないし、Yahoo!のアカウントも持ってないし、mixiなんかもってのほか。 よくわからんのだが、googleのOpenIDでFacebookやYahoo!にログインして、FacebookやYahooのアカウントが無かったら、新しく作るページかなんかが開くと思ってるんだが、違うか? 教えて。

MySQLiクラスをラップする

<?php /** * MySQLiクラスの拡張 */ class MySQLiDB extends mysqli { private $_host; private $_user; private $_pass; private $_db; private $_char; private $_timeout; public function __construct($host, $user, $pass, $db, $char, $timeout) { parent::init(); // AUTOCOMMIT オフ if (!parent::options(MYSQLI_INIT_COMMAND, "SET AUTOCOMMIT = 0")) { die("Setting MYSQLI_INIT_COMMAND failed"); } // 接続のタイムアウト 設定 if (!parent::options(MYSQLI_OPT_CONNECT_TIMEOUT, $timeout)) { die("Setting MYSQLI_OPT_CONNECT_TIMEOUT failed"); } // 接続 if (!parent::real_connect($host, $user, $pass, $db)) { die("Connect Error (" . mysqli_connect_errno() . ") " . mysqli_connect_error()); } // デフォルトのクライアント文字エンコーディング 設定 if (!parent::set_charset($char)) { die("Error loading character set {$char}: %...

ファイル名やディレクトリ名にスペースを含むときに使える!chmodで再帰的にアクセス権を設定する

現在のディレクトリ以下のファイルとディレクトリに対して、再帰的にアクセス権を設定するには find . -type f -print0 | xargs -0 chmod 644 find . -type d -print0 | xargs -0 chmod 755 とする。 -print0 | xargs -0 とすることで、名前にスペースを含むファイルやディレクトリが存在しても、処理してくれる。

mb_send_mail() するなら mb_convert_encoding() は不要

おれも勘違いしていたが、mb_send_mail()を使ってメールを送るとき、mb_convert_encoding()使って、ISO-2022-JPへ変換しなくていい。 具体的には、たったこれだけ。 <?php // 日本語だよって宣言して mb_language('ja'); // UTF-8で組んでるなら、文字エンコードをUTF-8に合わせて mb_internal_encoding("UTF-8"); // mb_send_mail()するだけ mb_send_mail("dare@doko.koko", "メールの送信テスト", "これは、メールの送信テストです。"); これだけで、 件名は、mb_encode_mimeheader(mb_convert_encoding("件名", "ISO-2022-JP", "UTF-8"), "ISO-2022-JP") してくれるし 本文は、mb_convert_encoding("本文", "ISO-2022-JP", "UTF-8") してくれる。 ただ、Fromに日本語使いたいときだけは、自前で $from = mb_encode_mimeheader(mb_convert_encoding("おれから", "ISO-2022-JP", "UTF-8"), "ISO-2022-JP")."<ore@doko.soko>"; ってやってから mb_send_mail("dare@doko.koko", "メールの送信テスト", "これは、メールの送信テストです。", "From:".$from); って送ってあげる。

SetEnvIf の Request_URI には Query String は含まれない

クエリストリングを含んでいたときだけ、ログに記録したくなかたったので、調べてみた。 まぁ、結論はタイトルに書いてあるのだが、 これを知らなかったおかげで、1時間無駄にした。 じゃあ、どうやって制御するかというとこんな感じ。 <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_URI} ^/hogehoge/index\.html RewriteCond %{QUERY_STRING} id=123 RewriteRule ^(.*)$ $1 [E=nolog:1] </IfModule> CustomLog "| /usr/sbin/rotatelogs /var/log/httpd/access_log.%Y%m%d 86400 540" combined env=!nolog /hogehoge/index.html はログに記録されるけど /hogehoge/index.html?id=123 はログに記録されない。

HTTP_HOST と SERVER_NAME の違い

あざーっす。 http://phpspot.org/blog/archives/2006/05/server_namehttp.html --2013/9/17 追記-- 上の説明を読んで色々試してみたんだけど、やっぱり違いがわからなかった。 そんな時は、やっぱりドキュメント読まなきゃね。 ■Apache HTTP サーバ バージョン 2.2 ドキュメント UseCanonicalName ディレクティブ

maillogの世代管理

maillogの世代管理を、デフォルトの4週間から1年(54週)に延ばす。 # cd /etc/logrotate.d/ # cp syslog mail # vi mail /var/log/maillog {     rotate 54     sharedscripts     postrotate         /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true     endscript } # vi syslog /var/log/messages /var/log/secure /var/log/spooler /var/log/boot.log /var/log/cron {     sharedscripts     postrotate         /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true     endscript }

header()で飛ばされてもリファラは

例えば、 http://www.example.dom/a.html の <a href="./b.php">リンク</a> のリンクを踏んで、b.php へ飛んだとする。 b.php が <?php header("Location: ./c.php"); ?> で、c.php が <?php echo $_SERVER['HTTP_REFERER']; ?> だった場合、c.php で echo されるリファラは http://www.example.dom/a.html となる。

postfix キュー削除

キューに溜まったメールを表示する。 mailq キューに溜まったメールの配信・転送を停止する。 postsuper -h ALL キューに溜まったメールから、特定のメールアドレスが含まれるメールを抽出する。 mailq | grep hoge@example.com キューに溜まったメールを消す。 postsuper -d メッセージID 停止した配信・転送を再開する。 postsuper -r ALL 今日はこれで救われた。

httpdの監視

httpdの監視 top -b -d 1 -n 10 1>> /var/tmp/top_`date +\%Y\%m\%d`.log 2>> /var/tmp/top_`date +\%Y\%m\%d`.log apachectl fullstatus 1>> /var/tmp/httpd_status_`date +\%Y\%m\%d`.log 2>> /var/tmp/httpd_status_`date +\%Y\%m\%d`.log こいつらをcronへ登録。

PHPで非同期処理

こんな感じで開始時刻をミリ秒ではいて、5秒間待つだけの処理を test_mulitproc.php <?php list($microSec, $timeStamp) = explode(" ", microtime()); error_log(date('Y-m-d H:i:', $timeStamp) . (date('s', $timeStamp) + $microSec)); sleep(5); 同じくこんな感じで実行してみると test_multiexec.php <?php error_log('同期処理開始'); exec('php /var/www/test_multiproc.php 1> /dev/null 2>&1'); exec('php /var/www/test_multiproc.php 1> /dev/null 2>&1'); exec('php /var/www/test_multiproc.php 1> /dev/null 2>&1'); exec('php /var/www/test_multiproc.php 1> /dev/null 2>&1'); exec('php /var/www/test_multiproc.php 1> /dev/null 2>&1'); error_log('非同期処理開始'); exec('nohup php /var/www/test_multiproc.php > /dev/null &'); exec('nohup php /var/www/test_multiproc.php > /dev/null &'); exec('nohup php /var/www/test_multiproc.php > /dev/null &'); exec('nohup php /var/www/test_multipr...

MTAとMUAと配信と転送と中継

メールのおべんきょ。 MTA(Mail Tranfer Agent) メールを配信したり転送を行うプログラムのこと。メールサーバはこの機能を有している。 MUA(Mail User Agent) MTA機能を持たず、ユーザのフロントエンドとして、電子メールの表示や読み書き、そしてメールサーバへの送信やサーバの自分のメールボックスからのメールの受信に専念するプログラム。 配信(delivery) MTAが 自分の所のローカルユーザーのメールボックスへ メールを送る事を「配信」と言 う。 転送(transport) 送信先が自分の所のローカルユーザーでない場合、 他のメールサーバーへメールを送る必要がある。MTAが他の メールサーバーへメールを送る事を「転送」と言う。 中継(relay) MTAが、MUAや他のMTAからのメールを「転送」することを「中継」という。 とこんな感じかな。 転送と中継の説明がなってないような気がするが... ツッコミよろしくです。

そのまま移行してやがった

...だめだ、ここ。 昔のソース、そのまま移行してやがった。 外部入力値は、htmlspecialchars()通すか、htmlentities()通すかのどっちかなのに、 昔のソースそのまま移行してあったから(っていうか、昔も間違ってんだけど) stripslashes()通した結果に対して、 「"」を「&quote;」にreplace()してた。 呆れてものもいえない。

PHPで2重ポスト対策 その2 同一ページ内で処理

流れのサンプルなので、XSSとかSQLインジェクションとか考慮してません。 なので、使うときは考慮してね。 <?php $act = isset($_POST['act']) ? $_POST['act'] : 'init'; $data = isset($_POST['data']) ? $_POST['data'] : ''; $ticket = ''; session_start(); // 初期化処理 if ($act == 'init') { $act = 'check'; } // チェック処理 else if (($act == 'check') || ($act == 'regist')) { if (チェック処理正常) { $act = 'regist'; $ticket = time(); $_SESSION['ticket'] = $ticket; } // 登録処理 else { // 2重ポスト時 if (empty($_SESSION['ticket'])) { // 2重ポストされたときの処理 } // 不正なポスト時 else if ($ticket != $_SESSION['ticket']) { // 不正な処理 } // 正常なポスト時 else { // 先にチケットを空にする unset($_SESSION['ticket']); // 登録処理 if (登録処理正常) { header("Location: 登録完...

リクエストはキャンセルできない

基本的なことを知らなかった。 <?php $fp = fopen('/var/tmp/hoge.txt', 'wb'); for ($i = 0; $i < 1000; $i++) { // カウンタをファイルへ出力 fwrite($fp, "{$i}\n"); // 1秒待機 sleep(1); } 千秒カウントし、カウンタをファイルに出力するPGを作ってみた。 このPGへブラウザからアクセスして、途中で [ Esc ] キーでキャンセルした。 つもりだった。 で、サーバー上のファイルを less コマンドで開いて [Shift] + G で何気に表示を更新していたら、ファイルにカウンタが出力され続けていた。 ・・・一度受け付けたリクエストは、サーバー上で処理が終わるか、サービスが再起動されるまで処理され続けることがわかった。 知らなかったおれ、恥ずかしい・・・

PDOのプリペアドステートメントで同じ名前のパラメータマーカは使えない

PDOでプリペアドステートメントを使うとき、クエリ中にパラメータマーカを指定するが、このとき、同じ名前のパラメータマーカは使えない。 でも、使ってもエラーにならない。 クエリの結果を精査すれば、クエリで想定した結果にならないためわかるのだが、テストが嫌いな俺は、クエリそのものを検査することにした。 // すべてのパラメータマーカを取得する。 preg_match_all('/(:[\w]+)/', $sql, $matches); // パラメータマーカの出現回数を得る。 $param = array_count_values($matches[1]); // 2回以上出現したパラメータマーカを調べる。 foreach($param as $key => $val) { if($val > 1) { echo "パラメータマーカ {$key} を {$val} 個検出しました。"; // ここでエラーを発生させるか、強制終了する。 } } こんな感じのロジックをPDOを継承したクラスに仕込んでおけばOK。 class dao extends PDO { const DAO_ERROR_PARAMETER_MARKER_DUPLICATED = 777; // 今回必要なところだけ記述 public function prepare($statement, $options = array()) { preg_match_all('/(:[\w]+)/', $sql, $matches); $param = array_count_values($matches[1]); foreach($param as $key => $val) { if($val > 1) { // エラーモードに応じて、例外を発生させるか、falseを返す。 $err_mode = $this->getAttribute(PDO::ATTR_ERRMODE); ...