コンピュータのトラブルシューティングに適した性格とそうでない性格がある。まあ、態度というか姿勢といってもいいが、どちらも性格から出てくるものだから、ここではまとめて性格と呼ぶことにする。
仕事でいつも対応しているのはウェブアプリケーションのトラブルだから、ここではその話に限定する。プリンタが動かないとか、マシンが重くなったとか、そういった問題は全部再インストールすればなんとかなることだから何もかも忘れてリストアして遠くの店に昼飯でも食べに行けばいいと思う。
ウェブアプリケーションのトラブルといってもいろいろある。これまで実際に直接または間接的に経験したものでも、アプリケーションのレベルの単なる不具合から、日頃のケアを怠ったせいで累積した問題が(比喩的にいえば)爆発してサービスが提供できない状態になっていたり、はたまたデータセンタが文字通り火事になっていたり、とにかくトラブルの原因も現象も千差万別だ。
そんな日常の中で、唯一といっていいほど必ず効果的なトラブルシューティングの手法があって、この逆をやると間違いなく二次災害や余計な手間になったり、運が良くてもその場の人間をみんなうんざりさせたりするのだが、それは
「パニくるな」
という黄金律で、とにかくこれが出来ない人間は絶対にトラブルが発生した現場に居てはいけないし、対応するなどもっての他だ。パニックを起こす理由はいろいろある。その人が全財産を投資して構築したシステムが目の前で崩壊しているのかもしれないし、単純に持っているスキルでは何をしていいのか見当もつかないのでひたすら慌ててしまっているのかもしれない。たいした能力もなく気が小さいくせに日頃から威勢のいいことを言いふらしておのれの実力以上に自己宣伝しているので急に本番がやって来て追いつめられたのかもしれない。だが、理由はともかく、パニックを起こしても問題解決にはいっさい何も寄与しない。
それから、自分がパニックしているかどうかを自分だけで知る方法は、自分の足を引っ張って空を飛ぶのと同じ要領で、つまり存在しない。だから、トラブルが発生したときに「ちょっと黙っててもらえますか?」「うるさい」などの言葉を投げつけられたり、トラブル対応中の人に何か質問しても無視されたら、これは自分がパニックしている証拠だと考えなければいけない。もちろん、そんなことを考えられるくらい冷静なら、そもそも文句などいわれないしパニックなど起こしてはいないので、結局は何の意味もないのだけれど。
ジーン・ウルフの短編によれば、未来世界でも「はた迷惑な人」をなんとかする薬は発明されていないそうだ。さもありなん。
Popularity: 6% [?]
WILLCOMがスーパーボーナス一括払いみたいなことを始めている。2年間の月額料金が980円とのことだが、機種代金を一括で支払ってしまったら月額料金はもっと下がってしまう。
Popularity: 4% [?]
Windows Liveからシュールなメールが。
Windows Live および MSN のお知らせメールの受け取り設定について
(中略)
現在、お客様の [お知らせメールの受信設定] におきまして、「Windows Live 製品または MSN 製品に関する情報をメールで受け取らない」設定になっております。今後、マイクロソフトより重要な製品更新情報についていち早くお客様にご連絡を差し上げたいと存じます。よろしければ、大変お手数ではございますが、お客様のアカウントのプロフィール (こちら) から、設定変更をお願いいたします。チェックボックスを外している状態が、「受け取る」の設定になります。
いや、だからこういうのを受け取りたくないからそうしてるんであって。
Popularity: 5% [?]
同僚がphpDocumentorのソースに変なことが書いてあるというので見ると、確かに変だ。長いコメント部分を除くとこうなっている。
#!/bin/sh
if [ -z "$PHP" ]; then
PHP=`which php`
fi
(exec $PHP -C -q -d output_buffering=1 "$0" "$@") 2>/dev/null
if [ "$?" -ne "0" ]; then
echo "FAILED: Bad environment variable \$PHP (set to \"$PHP\")"
exit 1
fi
exit 0
<?php
ob_end_clean(); // make output from autofind php code disapear
$test = @include "phpDocumentor/find_phpdoc.php";
if ($test == 6) {
// find_phpdoc.php returns 6
include "phpDocumentor/phpdoc.inc";
} else {
echo "Error: phpDocumentor not found" . PHP_EOL;
}
?>
シェルスクリプトが冒頭にきて、その中から今度はPHPとして実行されるように自分自身を呼び出して、しかもご丁寧に出力バッファリングでシェルのコード部分が出力されないようにしているよ!PHPはHTMLに埋め込まれる言語でもあるので、開始タグ「<?php」と終了タグ「?>」で囲まれていない部分はそのまま出力されるから、これでもちゃんと実行される。
それにしても、この手が使えるなら、シェルスクリプト以外の言語だって動かせるんじゃなかろうか。
さっそく実験。
#!/usr/bin/ruby
puts "This is Ruby!"
system("php -d output_buffering=1 -q #{__FILE__}")
exit
__END__
<?php
ob_end_clean();
print("This is PHP!\n");
exit;
?>
実行結果:
This is Ruby! This is PHP!
なんと!
この手を使えば、PHP on Ruby on Railsだって夢じゃない!PHP4からの移行が大変?冗談でしょ。これからはPHPはあらゆるスクリプト言語の上(下)で動く時代ですよ。
Popularity: 10% [?]
肺炎レンサ球菌という細菌があって、結構な割合で人間の体内にあるものなのだが、乳幼児や老人にとっては危険な強毒性の細菌である。 これはワクチンの接種で予防できるのだが、日本では承認されていない。Wikipediaの記事いわく:
2歳未満の乳幼児では、非蛋白抗原の免疫原性に期待できないため、23価不活化ワクチンの適応がない。このため、日本以外では多価蛋白結合肺炎球菌ワクチン(最もよく知られているものは7価)が使用されているが、日本では未承認であるから、個人輸入をしている医療機関での合法的接種が唯一の選択肢となる。
とのこと。 何がけしからんというと、うちの超絶的にかわいいまめぞうの血液の中にもこの肺炎レンサ球菌が見つかっているのだ。発症してしまうと大変なことになる。 たまたま選んだ小児科病院の医師の方が非常に丁寧で、電話で詳細な血液検査の結果を教えてくれて、肺炎レンサ球菌についても都内で数か所ワクチンを輸入している病院があることも聞くことができた。 しかし、これがいまだ無認可であることは非常に問題である。 厚生労働省に働きかけてもおそらくほとんど何も進展しないだろう。われらがゲイツ様であれば迷わず肺炎レンサ球菌をばらまいて優先順位を上げさせるだろうが、さすがにそれはちょっと難しい。市民運動もあるので署名とかで協力することはできる。 しかしだ、こういうのが本当だとすると、厚生労働省の人たちは働けといいたくもなる。というかいってやる。働け。 写真は挑発的な厚生労働省のサボタージュに怒り心頭のまめぞう。 
Popularity: 5% [?]
ブルース・シュナイアーの最近のエッセイに、ソーシャルネットワークのなり済ましテクニックが紹介されていた。
ソーシャルネットワークを使って成りすましをやってのける方法という記事があるらしく、シュナイアーのエッセイはその紹介なのだが、手口は次の通り(元記事ではMySpaceとFacebookだけど日本なのでmixiとgreeにしよう):
・適当な人にmixiでフレンドリクエストを送る
・フレンド登録してくれる人がいたらgreeでその人たちを探す
・greeでも見つかった人がいたら、そこでもフレンドリクエストを送る
これで準備完了。フレンドリクエストを送った相手が犠牲者になる。
・犠牲者のmixiとgreeの友達リストを見比べて片方にしか登録していない人を探す
・見つかったら、その人の写真とプロフィールをコピーして新規にアカウントを作る
・作ったアカウントから犠牲者にフレンドリクエストを送る
これで、かなり信憑性のある偽アカウントが出来上がる。あとは詐欺師のアイデア次第。
「今度飲みに行こうよ!18日に新宿とかどう?」で、やって来たところをボコボコにして金品を奪うとか。
確かに、複数のソーシャルネットワークを使っているとこれは引っかかりそうだ。気をつけないとなあ。
Popularity: 7% [?]
自然言語処理はPythonがいちばんという記事を読んで思い出したのだが、自分でもWordnetのPHP版フロントエンドをさくっと(Ruby版をコピーして)作っていた。ほんとまるコピーなのでほったらかしにしていたのだが、イテレータのところの醜さに悶絶してもいいなら責任は取らないが読むのは許可するので公開しておく。都市の空気は自由だ。
<?php
class Wordnet{
public $db;
function __construct($dsn){
$this->db =& $this->_connect($dsn);
}
function __destruct(){
}
public function singleton($dsn){
static $obj = null;
if(is_null($obj)){
$name = __CLASS__;
$obj =& new $name($dsn);
}
return $obj;
}
private function _connect($dsn){
static $dbh = null;
if(is_null($dbh)){
try {
$dbh = new PDO($dsn);
} catch(Exception $e) {
echo $e->getMessage();
}
}
return $dbh;
}
private function _exception(&$e){
echo $e->getMessage();
}
private function _select($sql, $param=array()){
$statement = $this->db->prepare($sql);
$statement->setFetchMode(PDO::FETCH_ASSOC);
if($statement->execute($param)){
return $statement->fetchAll();
}else{
$info = $statement->errorInfo();
foreach($info as $k => $v){
$message .= $k . ":" . $v . "\n";
}
throw new Exception($message);
}
}
private function _get($sql, $param){
try {
$array = $this->_select($sql, $param);
}catch(Exception $e){
$this->_exception($e);
return null;
}
return $array;
}
public function get_words($lemma){
$sql = "SELECT * FROM word WHERE lemma=?";
$array = $this->_get($sql, array($lemma));
return $array;
}
public function get_word($wordid){
$sql = "SELECT * FROM word WHERE wordid=?";
$array = $this->_get($sql, array($wordid));
return $array;
}
public function get_senses($wordid){
$sql = "SELECT * FROM sense WHERE wordid=?";
$array = $this->_get($sql, array($wordid));
return $array;
}
public function get_sense($synset, $lang='jpn'){
$sql = "SELECT * FROM sense WHERE synset=? AND lang=?";
$array = $this->_get($sql, array($synset, $lang));
return $array;
}
public function get_synset($synset){
$sql = "SELECT * FROM synset WHERE synset=?";
$array = $this->_get($sql, array($synset));
return $array;
}
public function get_syn_links($synset1, $link){
$sql = "SELECT * FROM synlink WHERE synset1=? AND link=?";
$array = $this->_get($sql, array($synset1, $link));
return $array;
}
public function get_sys_links_recursive($senses, $link, $lang='jpn', $depth=0){
if(is_array($senses)){
foreach($senses as $sense){
$syn_links = $this->get_syn_links($sense['synset'], $link);
if(count($syn_links) > 0){
$get_word = $this->get_word($sense['wordid']);
$synset = $this->get_synset($sense['synset']);
$space = str_repeat(' ', $depth);
print($space . $get_word[0]['lemma'] . ' ' . $synset[0]['name'] . "\n");
$tmp_links = array();
foreach($syn_links as $k => $syn_link){
$tmp_sense = $this->get_sense($syn_link['synset2'], $lang);
if($tmp_sense != ''){
$tmp_links[] = $tmp_sense[0];
}
}
$this->get_sys_links_recursive($tmp_links, $link, $lang, $depth + 1);
}
}
}
}
public function main($word, $link, $lang='jpn'){
if($words = $this->get_words($word)){
$senses = $this->get_senses($words[0]['wordid']);
$this->get_sys_links_recursive($senses, $link, $lang);
}else{
return "nothing found";
}
}
public function usage(){
$usage = >>>EOS
usage: wordnet.php word link [lang]
word word to investigate
link
syns - Synonyms
hype - Hypernyms
inst - Instances
hypo - Hyponym
hasi - Has Instances
mero - Meronyms
mmem - Meronyms --- Member
msub - Meronyms --- Substance
mprt - Meronyms --- Part
holo - Holonyms
hmem - Holonyms --- Member
hsub - Holonyms --- Substance
hprt - Holonyms -- Part
attr - Attributes
sim - Similar to
entag - Entails
causg - Causes
dmncg - Domain --- Category
dmnug - Domain --- usage
dmnrg - Domain --- Region
dmtcg - In Domain --- Category
dmtug - In Domain --- usage
dmtrg - In Domain --- Region
antsg - Antonyms
lang (default: jpn)
jpn - Japanese
eng - English
EOS;
print($usage);
}
}
$dsn = 'sqlite:./wnjpn-0.9.db';
$obj = Wordnet::singleton($dsn);
$word = $_SERVER['argv'][1];
$link = $_SERVER['argv'][2];
$lang = $_SERVER['argv'][3] ? $_SERVER['argv'][3] : 'jpn';
if($word == '' || $link == ''){
$obj->usage();
exit;
}
$obj->main($word, $link, $lang);
?>
ではテスト。
$ ruby wordnet.rb 'うんこ' hype うんこ dung 大便 stool うんこ turd 大便 stool $ php -q wordnet.php 'うんこ' hype うんこ dung 大便 stool うんこ turd 大便 stool
そもそもlinkとか意味がわかってないのでこれ以上テストする気がないのだが、動いていそうな雰囲気ではある。うんこしかテストしていないので、不自然な言語処理にぜひともおすすめ。
テストしてない上にローカルで使ってたのでセキュリティとか一切考慮してないから、これを使って何をしようとも愚挙としかいいようがないので念のため。
Popularity: 8% [?]



