twitterの最新のツイートをfacebookに投稿する。

twitterで指定したユーザーの最新のツイートをfacebookのウォールに投稿するPHPスクリプトを作りました。

このアプリのために作りました。

ただーし、実際にこれを動かすには、

  • facebook にアプリケーション登録をする。
  • アクセストークンを取得する。

という一見簡単そうだけど、めっちゃめんどくさい手続きが必要です。

以上が完了したら、以下のスクリプトの”YOUR …”の部分を修正して Cron でぶん回してください。

twitterのユーザー名は、コマンドライン引数で渡すようになっています。

あと、require してるファイルは facebook のPHP 用の SDK です。

Cronには、以下のように渡したほうが幸せになれると思います。

*/10 * * * * export LANG=ja_JP.UTF-8; /usr/bin/php /path/to/cron.php twitter_user

mysql_upgrade を実行する

昨日MySQLをアップグレードしたんですが、いろいろすったもんだした挙句、無事に動いていると思っていました。

しかし、ログをよく確認すると以下のようなログが。。。

110420 21:20:14 [ERROR] Column count of mysql.
proc is wrong. Expected 20, found 16.
Created with MySQL 50044, now running 50511.
Please use mysql_upgrade to fix this error.

どうやら問題があるので mysql_upgrade をしてね。ということらしい。

mysql_upgrade とは?

MySQLのリファレンスに以下のようなページがありました。

MySQL のアップグレードでは、その度に、mysql_upgrade を実行します。これにより、データベース内のテーブルにおける最新の MySQL Server との互換性をチェックすることができます。該当テーブルが非互換の場合は、チェックの対象になり、問題があれば、そのテーブルを修正します。mysql_upgrade コマンドは、システム テーブルのアップグレードも行うため、新たな権限と追加機能を使用できるようになります。

MySQLをアップグレードしたら、mysql_upgradeをしてね。だそうです。知らんかった。

mysql_upgrade のやり方

mysqld が起動している状態で以下のコマンドを実行する。

mysql_upgrade -u root -p

-p はパスワードプロンプトを出してねという意味なので、環境に応じて。

というわけで、エラーログもでなくなりました。

WordPressのソースを検索するのに便利なコマンド

今日の記事は、WordPress開発で便利なコマンドの話です。

WordPressのプラグインを開発していると、フックを探したり特定の関数のソースを見る必要があったり、定数を確認したかったり、いろんな場面でWordPressのソースを検索する必要があります。

以下はLinuxやMacのターミナルでそれらを検索する方法です。

WordPressはコーディング基準が定められているので、こういう時には超便利です。

コマンドで複数ファイルの検索を行うには?

私は、find と xargs、grep という3つのコマンドを組み合わせて検索しています。

find /path/to/wordpress -name "*.php" | xargs grep "foo"

上記のコマンドでは、/path/to/wordpress ディレクトリ内(サブディレクトリも含む)の全ての.phpファイルから、ファイル内に”foo”が含まれるファイルを検索しています。

WordPressの全てのアクションフックを検索する。

あらかじめWordPressのディレクトリに移動してから以下のコマンドを入力してエンター。

find . -name "*.php" | xargs grep "do_action("

WordPressの全てのフィルターフックを検索する。

find . -name "*.php" | xargs grep "apply_filters("

WordPressで定義されている全ての定数を検索する。

find . -name "*.php" | xargs grep "define("

WordPressの特定の関数のソースを探す

たとえば、get_option() のソースがどこにあるのかを知りたければ、以下のようなコマンドで。

find . -name "*.php" | xargs grep "function get_option"

具体的に開発中にどう使うの?

たとえば、コンテンツthe_content()の中身を修正するプラグインを作成するには、the_content()のソースがどのファイルにあるのかを探します。

find . -name "*.php" | xargs grep "function the_content"

上記のコマンドを実行すると wp-includes/post-template.php というファイルにあるのがわかります。

で、実際にソースを見ると、the_content というフィルターフックがあるのがわかるので、そのフックを使用して書き換えるといった感じです。

実際には、対象の関数からさらに別の関数がコールされていたりするので、何回もこのコマンドを打つ感じになりますが。
(お役所のたらいまわしに似てるかも。)

phpのescapeshellarg()に日本語を渡す際の注意

めっちゃハマったのでメモ。

これはマニュアルにも記載されていないみたい。

escapeshellarg() の引数に日本語を渡す

もともと別のサーバーで動作していたphpスクリプトを別のサーバーに移行した際に、以下のような不具合に遭遇した。

<?php

$tmp = '日本語';
$tmp = escapeshellarg($tmp);

echo $tmp; // $tmpの中身がカラ!?

?>

要はescapeshellarg()に日本語を渡すと値がカラ(シングルクォートのみ)になるということ。

原因

いろいろ調べた結果、どうやらescapeshellarg()は、OS側の環境変数LANGの値によって挙動が変わるらしい。

今回はインストール直後の某VPSに移行したばかりだったのでLANGが設定してなかった。

そこで、/etc/sysconfig/i18nに以下のような記述を追加したら正常に動作した。

LANG=ja_JP.UTF-8

無効なマルチバイト文字列は処理しないということらしい。

なるほど、かしこい!

Webサーバーの稼働状況を定期的にチェックする

先日データーセンターでネットワークトラブルがあって、そのトラブルそのものはうちの問題ではなかったので、おまかせにしていたら数時間で復旧したのだが、トラブルに弊社が気づくのが遅れてしまい、お客様に余計な心配をかけてしまった。

そんなわけで、外部のサーバーからWebサーバーの稼働状況を監視するPerlスクリプトを作成して、Cronでぶんまわすことにした。

仕組み

仕組みはとても簡単で、ざっと以下のような感じ。

  1. コマンドライン引数に渡されたURLに対してwgetを実行する。
  2. 実行した結果を評価して、エラーがあればメールを送信する。

という感じ。

wgetコマンドを実行する際に実際にファイルをダウンロードしちゃうと面倒なので、以下のようなオプションをつけた。

my $com = "/usr/bin/wget -q -o /dev/null --spider '".$url."'";

ちなみに、pingだとネットワークトラブルしか検出できないが、wgetならネットワークが生きていてapacheが死んでるなんていうシチュエーションも拾ってくれる。

使い方

以下のように、このPerlスクリプトにURLを引数で渡して、Cronに登録する。

*/10 * * * * /path/to/lifecheck.pl http://www.example.com/

ちなみに、Cronに自前スクリプトを登録する際は環境変数によって挙動が変わったりするので、以下のように環境変数をundefしちゃうと都合が良いと個人的に思うのだが。みんなはどうしているんだろう?

undef %ENV;

ソース

以下のソースをコピペして、lifecheck.plというファイル名で任意のパスに保存する。

#!/usr/bin/perl -wT

undef %ENV;

use strict;
use warnings;
use Encode;
use utf8;
use Mail::Sendmail;

my $from 	= 'admin@example.com';
my $to 		= 'you@example.com';

my $reg = q{^https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+$};

my $in = shift @ARGV;

my $url = '';
if ($in =~ /($reg)/) {
    $url = $1;
}

if (!$url) {
    die('url?');
}

$url =~ s/'/'\''/g;

my $com = "/usr/bin/wget -q -o /dev/null --spider '".$url."'";
system($com);

if ($?) {
    &mailto(
        $from,
        $to,
        '['.$url.'] Alert',
        "Can not connect Web Server.\nPlease check below.\n".$url
    );
}

sub mailto
{
    my ($from, $to, $subject, $body) = @_; 

    $subject = encode('MIME-Header-ISO_2022_JP', $subject);
    $body = encode('iso-2022-jp', $body);
    my %mail;
    $mail{'Content-Type'} = 'text/plain; charset="iso-2022-jp"';
    $mail{'From'} = $from;
    $mail{'To'} = $to;
    $mail{'Subject'} = $subject;
    $mail{'message'} = $body."\n";
    sendmail %mail;
}

rsyncで.svnを除外

rsyncでファイルを転送するときに、ほとんどの場合に(あくまでも私の場合!)、.svnは邪魔だということに今更気がついた。

というわけで、.bash_profileに以下の行を追加した。

alias rsync="rsync -avz --exclude=\".svn\""

これで、転送した後にfindとか使って.svnを削除したりしなくてすむ。

ちなみに、私の.bash_profileは以下のような感じ。

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

alias svndel="svn st | grep '^!' | sed -e 's/\![ ]*/svn del /g' | sh"
alias svnadd="svn st | grep '^?' | sed -e 's/\?[ ]*/svn add /g' | sh"
alias rsync="rsync -avz --exclude=\".svn\""
alias vi="vim"

export PATH
export LANG=ja_JP.UTF-8
PS1="[\u@\h \W]\$ "

シェルコマンドでシングルクォートに囲まれたシングルクォートのエスケープ

たとえば、シングルクォーテーションを使用したディレクトリ名を作成したい場合、以下のようにコマンドを入力することで、ディレクトリ名にシングルクォーテーションが使用できる。

$ mkdir test\'

つまり単純にシングルクォーテーションをバックスラッシュでエスケープしてやればよい。

削除したいときも同じ。

$ rm -fr test\'

ここまでは普通。

では、ディレクトリ名をシングルクオーテーションで囲みたいときはどうするのか?
通常、ターミナルでコマンド入力するときは、このようなシチュエーションはないが、PerlやPHPからsystem()などでコマンドを実行したい場合に、そうしたいときがある。

すくなくとも、このときはそう思った。(恥)

実はこの場合、バックスラッシュでエスケープしても意味が無い。

$ rm -fr 'test\''  # これではダメ

そこで、phpのescapeshellargがどうしているのかを確認した結果、いかのようにするのが正しいことがわかった。

$ rm -fr 'test'\'''

なんか腑に落ちない気もするが、実際にこれでうまくいったので。。。ちょっと不安。

LnuxコマンドでPDFからJpegに変換する(2)

前回の記事で、PDFからJpegに変換する方法を書いたのだが、いろいろなPDFを試しているうちに、問題を発見した。

方向が判別できていない?

たとえばA3横長のPDFをJpegに変換する際に、なぜか左に90度回転してしまい縦長の画像で出力されるという現象に直面した。

PDFとしては横長で表示されているにもかかわらず。。。

最初は、安易に右に90度傾けるように-rotate 90なんてパラメータを追加していたのだが、別の横長のPDFで今度は逆に右に90度傾いてしまうということに気がついた。

要は同じA3横長のPDFでもPDFによって結果が違うらしい。

問題はPDFを作る際の「印刷の向き」だった。

ImageMagickのconvertコマンドは、GhostScript経由でPDFから画像を作っているようだったので、GhostScriptの設定?と思いいろいろ調べていたのだが、結論はPDFを作る際の「印刷の向き」にあった。

印刷の向き

横長の画像を作りたいときは、上記の赤枠内で「横」を選択すれば、期待通りの方向で画像が作成された。

原因が分かれば、非常に納得のいくことだった。

ちなみにMacOSXにMacPorts経由でインストールしたconvertコマンドでは、このあたりのことは気にする必要がなく、つねに表示と同じ方向で画像が作成されたので、ある程度環境にも依存することなのかもしれない。

LnuxコマンドでPDFからJpegに変換する

PDFをJpegに変換するコマンドを調べていたら、xpdfまたはpoppler-utilsパッケージに含まれるpdftoppmライブラリを使用するという情報をいくつか見つけた。

実際に、社内の環境でテストしたところ紹介されていた方法でうまくいったのだが、本番環境のCentOS5ではxpdfをいれてもpoppler-utilsをいれてもpdftoppmコマンドがインストールされなかった。

あれこれ、調べているうちに、どうやらCentOS5ではRPMパッケージのバグ?か何かの理由によりpdftoppmがインストールされないらしいということがわかった。

幸いImageMagickでも同じことができるという情報もあったので、それをつかって高解像度のJpegを出力することができないか試してみた。

ImageMgickでPDFをJpegにきれいに変換する。

「ImageMagickでPDFをJpegに変換すると綺麗にならない」との指摘はいくつかのブログで見かけた。

だが、しつこく調べた結果、パラメータを追加することでpdftoppmを経由するのと同じぐらい綺麗なPDFを出力できた。

convert -density 600 -geometry 1000 in.pdf out.jpg

上記のように-densityパラメータを設定すると綺麗なPDFを出力できる。

画像とか印刷とかには詳しくないのでよく分からないのだが、上記の例では解像度600dpiで横幅1000pxのJpegを作るよう指定している。
解像度とピクセルの値が矛盾しているような気がするのだが、こうすることで明らかにJpeg画像が綺麗になった。

mieki256′s diary – ImageMagick convert のオプション

antialiasを指定したときの違いは手元のPDFではあまり分からなかった。

PDF内の一部のページのみをJpeg化する場合は以下のようにページ番号を指定する。

convert -density 600 -geometry 1000 in.pdf[0] out.jpg

各パラメータの値は、もっとたくさんのPDFで試してみないとわからないかもしれない。

Linuxでユーザーの追加、削除

こんなコマンド「いまさら。。。」なのですが、本日ユーザーを削除する必要が出てきて、よく考えたらいままでは/etc/passwdなどを直接触っていたのですが、あんまりよくないだろうということで、Google先生に聞いた結果をメモ。

ユーザーの追加

useradd [-g GROUP] [-d HOME_DIR] LOGIN

ユーザーの修正

usermod [-g GROUP] [-d HOME_DIR] LOGIN

ユーザー名の変更

usermod -l NEW_LOGIN LOGIN

ユーザーの削除

userdel [-r] LOGIN

パスワードの変更

passwd LOGIN

アカウントのロック

passwd -l LOGIN

アカウントのロック解除

passwd -u LOGIN