2012年3月29日木曜日

apt-getのpost-installationスクリプトエラー

パッケージインストール時に中途半端な状態になってしまったのか、対象のパッケージを apt-get purge や install -f, autoremoveしようとするが、エラーになってしまう状態になりました。

isuzuki@isuzuki-VirtualBox:~$ sudo apt-get purge oracle-java7-installer

---省略---

oracle-java7-installer を削除しています ...
update-alternatives: エラー: `build' は不明な引数です
dpkg: oracle-java7-installer の処理中にエラーが発生しました (--purge):
サブプロセス インストール済みの pre-removal スクリプト はエラー終了ステータス 2 を返しました
dpkg: クリーンアップ中にエラーが発生しました:
サブプロセス インストール済みの post-installation スクリプト はエラー終了ステータス 10 を返しました
以下のパッケージの処理中にエラーが発生しました:
oracle-java7-installer
E: Sub-process /usr/bin/dpkg returned an error code (1)

パッケージに関して確認
isuzuki@isuzuki-VirtualBox:~$ sudo dpkg --audit
以下のパッケージは最初の設定中に問題が発生したため、設定が終了していません。
dpkg --configure <パッケージ> か dselect で設定 (configure) メニューオプショ
ンを使って設定作業を再試行しなければなりません:
 oracle-java7-installer Sun Java(TM) Development Kit (JDK) 7

configure実行
isuzuki@isuzuki-VirtualBox:~$ sudo dpkg --configure oracle-java7-installer
oracle-java7-installer (7u3-0~webupd8~8) を設定しています ...
dpkg: oracle-java7-installer の処理中にエラーが発生しました (--configure):
 サブプロセス インストール済みの post-installation スクリプト はエラー終了ステータス 10 を返しました
以下のパッケージの処理中にエラーが発生しました:
 oracle-java7-installer
参考にさせていただいた、エントリに書いてあった通り、
/var/lib/dpkg/info の以下のファイルを削除しました。
oracle-java7-installer.postinst
oracle-java7-installer.postrm
oracle-java7-installer.prerm


再度configure実行
isuzuki@isuzuki-VirtualBox:~$ sudo dpkg --configure oracle-java7-installer
oracle-java7-installer (7u3-0~webupd8~8) を設定しています ...

試しにインストール
isuzuki@isuzuki-VirtualBox:~$ sudo apt-get install oracle-java7-installer
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています               
状態情報を読み取っています... 完了
oracle-java7-installer はすでに最新バージョンです。
正常な状態になったようです。

より詳しくは、参考にさせていただいたエントリ
非常に勉強になり、再びこのような事態が起きても対応できるように覚えておこう思います。

2012年3月25日日曜日

PHPでscanf

PHP extension の勉強をしていて、C言語を久々に触っていた時に、PHP で scanf みたいなのって書いたことないなと思ったので、調べて書いてみました。

こちらのエントリに書いてあったことをそのまま試してみました。

・scanf のサンプル
<?php
echo '文字列を入力してください。' ."\n";
fscanf(STDIN, '%s', $str);
var_dump($str);

echo '文字列を入力してください。' ."\n";
$stdin = fopen('php://stdin', 'r');
$str = trim(fgets($stdin));
fclose($stdin);
var_dump($str);


・実行結果


どちらも求める結果になりました。
違いに関しては、僕が参考にしたエントリを見ていただければと思います。

2012年3月20日火曜日

PHP5.4、配列文法

PHP5.4 から配列を簡単に書けるようになりました。

・今までの配列定義
<?php
$arr = array('a' => 'test1',
'b' => 'test2',
'c' => 'test3',
);


・新たな配列定義
<?php
$arr = ['a' => 'test1',
'b' => 'test2',
'c' => 'test3',
];


配列定義をループさせてみましたが、特にパフォーマンスに差はありませんでした。
今まで使用してきた言語によると思いますが、PHP5.4以前のころから利用している人は、新しい書き方はあまりしないかもですね。

2012年3月19日月曜日

PHP5.4インストール、Traitsの利用

PHP5.4が安定版としてリリースされたので、インストールしてみました。
インストール手順はこちらの記事を参考にしました。

・ソース取得
wget http://www.php.net/get/php-5.4.0.tar.gz/from/jp.php.net/mirror -O php-5.4.0.tar.gz

・tarファイル展開
tar xvf php-5.4.0.tar

・コンパイルオプション設定
cd php-5.4.0
./configure --enable-mbstring \
--prefix=/usr/local/php \
--enable-mbregex \
--with-zlib=/usr/local/zlib \
--with-zlib \
--enable-zip \
--enable-ftp \
--enable-pcntl \
--enable-soap \
--with-mcrypt \
--with-gd \
--enable-pdo \
--with-pear \
--with-readline \

・make、インストール
make
sudo make install

・確認


これでPHP5.4のインストールが完了しました。


新機能の Traits を試してみました。
Traits はソースの再利用に有効になるかもしれません。詳しくはマニュアル に書いています。

Traits を利用したシングルトン
<?php
trait TraitSingleton {
private static $_instance;

private function __construct() {
}

public static function getInstance() {
if (isset(self::$_instance) === false) {
self::$_instance = new static;
}

return self::$_instance;
}
}


シングルトン Traits 利用
<?php
require_once('/home/isuzuki/dev/php/php5.4/TraitSingleton.php');

abstract class Base {
}

class TraitSample1 extends Base {
use TraitSingleton;

private function __construct() {
}

public function echoClass() {
echo __CLASS__ ."\n";
return true;
}
}

class TraitSample2 extends Base {
use TraitSingleton;

private function __construct() {
}

public function echoClass() {
echo __CLASS__ ."\n";
return true;
}
}

$obj1 = TraitSample1::getInstance();
$obj1->echoClass();
$obj2 = TraitSample2::getInstance();
$obj2->echoClass();


実行結果


これで、Traitsが無事利用できていることがわかりました。

2012年3月12日月曜日

HipHop for PHP インストール

FacebookのHipHop for PHPをUbuntu 11.10にインストールしてみました。
手順は、Facebookが公開している手順(Building and Installing on Ubuntu 11.10)どおりに行えば問題ないです。

何点かインストール中に躓いたところで、OSを32bitにしていたので、cmakeの時点でwarningが出ました。
32bitでのcmake結果です。


32bitでも動かせるようですが、OSを64bitにして再トライしました。

同様の手順で、cmakeしたところ、特に何もメッセージも出ないので、続けてmakeし、実行しました。
ソースの修正を見逃していて、segmentation faultで落ちました。

こちらも、手順に書いてあるように、
lib/ssluse.c をgit hubのとおりに修正、
src/runtime/ext/extension.cpp も同様にgit hubのとおりに修正。

make後、無事実行できることを確認しました。

サンプルプログラムを、HipHopで実行してみました。
・PHPソース
<?php
echo 'HipHop for PHP' ."\n";
echo 'Hello World' . "\n";


実行結果


実行後、指定したディレクトリ以下には実行ファイルや、C++に変換されたソースなどがありました。
実行ファイルの結果


・C++ソース
/tmp/hphp/php/home/isuzuki/dev/php/hello.cpp

#include <runtime/base/hphp.h>
#include <sys/literal_strings_remap.h>
#include <sys/scalar_arrays_remap.h>
#include <sys/scalar_integers_remap.h>
#include <sys/global_variables.h>
#include <sys/cpputil.h>
#include <php//home/isuzuki/dev/php/hello.fws.h>
#include <php//home/isuzuki/dev/php/hello.h>

// Dependencies
#include <runtime/ext/ext.h>
namespace hphp_impl_starter {}

namespace HPHP {
////////////////////////////////////////////////////////////////////////////
///

/* preface starts */
extern CallInfo ci_;
/* preface finishes */
Variant pm_php$$home$isuzuki$dev$php$hello_php(bool incOnce, LVariableTable*
variables, Globals *globals) {
PSEUDOMAIN_INJECTION(run_init::/home/isuzuki/dev/php/hello.php, pm_php$$ho
me$isuzuki$dev$php$hello_php);
LVariableTable *gVariables ATTRIBUTE_UNUSED = (LVariableTable *)g;
echo(NAMSTR(s_ssedffcbbc, "HipHop for PHP\n"));
echo(NAMSTR(s_ssc9bf8a1a, "Hello World\n"));
return true;
}
namespace hphp_impl_splitter {}

////////////////////////////////////////////////////////////////////////////
///
}


/tmp/hphp/php/home/isuzuki/dev/php/hello.fws.h


#ifndef __GENERATED_php__home_isuzuki_dev_php_hello_fws_h6d9aa4dd__
#define __GENERATED_php__home_isuzuki_dev_php_hello_fws_h6d9aa4dd__


namespace HPHP {
////////////////////////////////////////////////////////////////////////////
///

// 1. Static Strings
extern StaticString s_ssc9bf8a1a;
extern StaticString s_ssedffcbbc;

// 2. Static Arrays

// 3. Static Variants





////////////////////////////////////////////////////////////////////////////
///
}


#endif // __GENERATED_php__home_isuzuki_dev_php_hello_fws_h6d9aa4dd__


/tmp/hphp/php/home/isuzuki/dev/php/hello.h


#ifndef __GENERATED_php__home_isuzuki_dev_php_hello_h344dcfd5__
#define __GENERATED_php__home_isuzuki_dev_php_hello_h344dcfd5__


// Declarations

namespace HPHP {
////////////////////////////////////////////////////////////////////////////
///

// Includes and Functions
Variant pm_php$$home$isuzuki$dev$php$hello_php(bool incOnce, LVariableTable*
variables, Globals *globals);

// Constants

////////////////////////////////////////////////////////////////////////////
///
}

#endif // __GENERATED_php__home_isuzuki_dev_php_hello_h344dcfd5__


このようなソースができていました。
これで、インストールは完了したので、今後色々と使ってみようと思います。

2012年3月1日木曜日

ファイルダウンロード

PHPでcsvファイルをダウンロードするサンプルプログラムを作成してみました。

最初のソースはファイルを作成して、ダウンロードさせるパターンです。
ファイル内容が、膨大な量になる時はこちらの方法がいいのかと思います。
<?php
$file = '/tmp/file.csv.' .getmypid();
$fp = fopen($file, 'w');
if ($fp === false) {
error_log('file open error');
exit(1);
}

$header = array('num',
'line',
'data',
);
fputcsv($fp, $header);

for($i=1;$i<=100;$i++) {
$line = array($i,
'line' . $i,
'data' . $i,
);
fputcsv($fp, $line);
}

fclose($fp);

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="download.csv"');
header('Content-Length: '.filesize($file));
readfile($file);

@unlink($file);
exit(0);



二つ目のソースは出力バッファを利用したものになります。
自分はファイルの内容問わず、ファイルを作成する方法でやっていたのですが、内容が大した量ではないときはこちらの方法の方が効率良いかと思います。
<?php
$fp = fopen('php://output', 'w');
if ($fp === false) {
error_log('file open error');
exit(1);
}

ob_start();
$header = array('num',
'line',
'data',
);
fputcsv($fp, $header);

for($i=1;$i<=100;$i++) {
$line = array($i,
'line' . $i,
'data' . $i,
);
fputcsv($fp, $line);
}

$str = ob_get_contents();
fclose($fp);
ob_end_clean();

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="download.csv"');
header('Content-Length: '.strlen($str));
echo $str;

exit(0);



入出力ストリームへのアクセスとか全然知らなかったので、非常に勉強になりました。
PHPマニュアル