Apache2.4.3上でPHP5.4.7を、間違えてCGIとして動かそうとしてハマった

WordPressをいじるために、Wondows7上に「Apache + PHP」の環境を準備していてハマった。

Apache起動して、phpinfo()を表示させようとしたら、InternalServerErrorとかになる。
Apacheのエラーログ見てみると、スクリプトの頭に#!ってつけろと言われた。

~~/phpinfo.php is not executable; ensure interpreted scripts have "#!" or "'!" first line
 ~~(9)Bad file descriptor: [client ::1:49361] AH01222: don't know how to spawn child process: ~~/phpinfo.php

PerlとかPythonのCGIスクリプトは、確かに#!/usr/bin/perlとかって書くけど、phpinfo()のスクリプトにはいらないはず。
が、いろいろ調べてみてもいまひとつわからず。。
ためしに、スクリプトの頭に#!C:\[PHPインストール先]\php.exeと書いてみると、なんか実行された。がブラウザの画面は、HTMLがそのまま表示された感じになってる。

わけわかんね。

で、タスクマネージャでhttpd.exeのプロセスをよく見ると、SYSTEMユーザで起動していた。
そういえば僕は、環境変数のPATHにphp.exeのディレクトリを追加するときに、ユーザの環境変数に追加していた。
システム環境変数のほうに記載しておかないと、SYSTEMユーザのPATHに設定が反映されていなくて、php.exeを見つけられないのかも!?
とおもってPATH設定をいじってみたけどダメ、、
ダメもとでPC再起動とかしてみたけど、やはりダメ。

Apache+PHPの環境は、昔WindowsXP上で触ったことあったし、こんなところでハマるはずねーよ。と途中で切れそうになりながら、調べていくとこれが原因だった。

AddHandler cgi-script .cgi .php

cgi-scriptとしてphpファイルを認識させているせいで、単体のスクリプトを実行するときのように、ファイルの頭に#!~が必要になっていたみたい。なんだこりゃってかんじ。
とりあえず、phpの記述を消してみたらうまくいった。

AddHandler cgi-script .cgi

PythonやPerlの場合はCGIとして動かすけど、PHPはCGIじゃないってことなんだろうか。
言語の違いではなくて、動作モードの違いかな?
ごっちゃになってる?


9/30追記

> タスクマネージャでhttpd.exeのプロセスをよく見ると、SYSTEMユーザで起動していた。

これ、やっぱり大事だった。php.exeへのPathの設定は、ユーザの環境変数ではなくシステム環境変数のほうに設定しておく必要がある。

PHPを動かすだけであれば、ユーザの環境変数のほうに設定しても大丈夫そうな感じだった(phpinfoが見れた)んだけれど、そのあとWordPressをインストールしようとしてエラーが出た。

「お使いのサーバーの PHP では WordPress に必要な MySQL 拡張を利用できないようです。」

php.iniの中でMySQLのextemsionを読込ませる設定がうまく有効にならないみたいで、wordpressからDBへの接続がうまくいかなかった。phpinfoを見る限り、MySQL用のモジュールは読み込まれているみたいだったんだけど・・・

で、システム環境変数のPATHに、phpへのパスを追加したら、wordpressがうまく動くようになった。

Advertisements

Norton Internet Security 2012 をアンインストールしたら、デバイスマネージャに何も表示されなくなった

1か月前にHPのノートPCを購入したんだけれども、そのPCにはノートンインターネットセキュリティ2012(60日間試用版)が入っていました。
昔使っていたiMacで使っていたウィルスバスター(Win,Mac版)のライセンスが余っているので、60日経ったら、いったんそちらに切り替えるつもりでいました。

で、60日経ったので、Nortonのアンインストールしてウィルスバスターのインストールしたら、PCの指紋認証機能が動かなくなりました。
HP SimplePassという指紋認証の設定ソフトを見てみたけど、原因はよくわからず。
ただ、デバイスを認識できていない雰囲気だったので、デバイスマネージャを起動して確認しようと思ったら、デバイスマネージャの画面が真っ白になっていて、何も表示されていないよ!!
わけわかんね

インターネットにはつなげられるのでネットワークは大丈夫そう。だけど、「ネットワークと共有センター」から「アダプターの設定の変更」を選択するとそっちの画面も真っ白。NICの設定ができないよ。
あと、地デジ見れなくなってました。
さらに、「コントロール パネル」-「ハードウェアとサウンド」-「デバイスとプリンター」を開いてみると、表示されているデバイスの数が、すげー少ない・・・

いろいろ調べてみたが、一般的な解決法が使え無さそうだったため、結構悩んだ。
バックアップを取っていなかったので、いよいよWindows再インストールかもしれないなと、最高に凹んだけども、偶然にも前日のWindowsUpdateで自動的に「復元ポイント」が取得されていた。
なので、前日の復元ポイントにもどして、デバイスの認識を正常な状態にした後、中途半端なインストール状態になっているNortonの設定を、「手動でファイル削除・レジストリ削除」してなんとかなった。

だが、しかし、まじでハマった。

Nortonに怒り心頭。その怒りを発信せずにいられない。
怒りの復旧手順を以下に書いておきます。

僕の使っているPC
HP Pavilion dv7-7000
Windows7 Home Premium (64bit)


(1)一般的な対処法は?

まずは「デバイスマネージャが真っ白」になったときの、一般的な対処法を調べた。
とりあえずここにまとまっている → Device Manager is blank – Microsoft Answers

<Method 1:>Plug and Playサービスが起動しているか

「スタートボタン」-「プログラムとファイルの検索」のところに、services.mscと入力し、サービスの一覧を開く。

Plug and Playサービスを右クリックし、プロパティを開く。スタートアップの種類が、自動起動になっていることを確認。サービスの状態が起動になっていることを確認。この設定になっていない場合は、設定変更したのちPC再起動。PC再起動したあと、Plug and Playサービスが起動していることを確認。

僕の場合、Plug and Playサービスが起動しているのに、デバイスマネージャの画面が表示されていませんでした。
なので、次のMethod2のレジストリ設定の確認に進みました。

<Method 2>レジストリの権限設定がおかしくなっていないか

まず、レジストリの変更は危険なので、バックアップを取得してください
Windows XP でレジストリをバックアップおよび復元する方法

「スタートボタン」-「プログラムとファイルの検索」のところに、regedt32と入力し、サービスの一覧を開く。

Enumのところまでツリーを開く
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum

Enumを右クリックし、アクセス許可を開く。
Everyoneユーザの権限を、「読み取り」のみに設定
SYSTEMユーザの権限を、フルコントロールに設定

僕の場合、きちんと権限設定がされていました。なので、ここも何もすることがなく、次の手順にすすみます。

(2)復元ポイントへのリカバリを試す

「スタートボタン」-「コンピュータ」を選択し、右クリック。プロパティを選択。
左の一覧に「システムの保護」があるので、それをクリックし「システムのプロパティ」画面を開く。
「システムの保護」タブの中の、「システムの復元」ボタンをクリック。

復元ポイントの一覧が表示されるので、復元したいものを選択します。
ここで「影響を受けるプログラムの検出」ボタンを押すと、復元することで影響のあるアプリが出てきます。
復元ポイントを取得した後にアップデートしたアプリは、「システムの復元」処理でなんらかの影響が出る可能性があるんだと思います。僕の場合、いろいろなソフトが該当していたんだけれども、メールデータがなくなると痛いので、メールソフト(thunderbird)のデータを念のためバックアップしておきました(結果的に、システムの復元をした後、メールソフトには何も問題ありませんでした)

システムの復元を実行すると、PC再起動になります。また、現時点での「復元ポイント」が自動的に取得されます。なので、復元したあとに、復元のキャンセルを行うことができます

僕の場合、システムの復元を行うことで、デバイスマネージャの画面が正常となりました。
地デジもOKとなり、ネットワーク設定も参照可能となりました

ただ、Nortonが中途半端な形で復旧されており、「OSからの見え方はインストールされている状態だが、実際のアプリ本体は無い」という状態ため、ウィルスバスターをインストールできません(ほかのウィルスソフトが入っているため、インストール中止します、って結果になる)
「コントロール パネル」-「プログラムのアンインストール」からNortonをアンインストールしようとしても、アンインストール処理が動きません(実体がないですからね・・・)

というわけで、中途半端な状態のNortonの残骸を、手動でアンインストールすることになりました。

(3)Nortonを手動でアンインストール

アンインストールについては以下のサイトを参考にしました。ただ、OSのバージョンが古いため、Windows7に読み替えながら行う必要があります。
ノートンインターネットセキュリティー2007を入れたらDVDドライブが読み込まなくなりました。 | デスクトップPCのQ&A【OKWave】

<手順1> コントロールパネルでノートン製品をアンインストール
「コントロール パネル」-「プログラムのアンインストール」からNortonInternetSecurityを右クリックして、アンインストールをします。僕の場合、Nortonの実体がないため、ここではアンインストールできませんでした。
ただ、もしアンインストールできたとしても、このやり方だと再び「デバイスマネージャが真っ白」状態になるので、だめです。

<手順2> [Norton Removal Tool] を使用

似たようなサイトがあるんだけれども、Win7ではこちらを使えばよさそうでした。
ノートン削除ツールをダウンロード、実行して、ノートン 360 をアンインストールする方法

ダウンロードしたファイルを実行するときれいにNortonが削除されました。
が、僕の場合、デバイスマネージャを開くと、一部のデバイスにびっくりマークがついてしまいました。
指紋認証デバイスと、地デジのデバイスがおかしくなっている模様・・・
ためしに地デジチューナ起動してみると・・・やっぱテレビ見れねぇ。

しかたがないから、またシステムの復元で復旧を行いました。。
というわけで、この手順もだめでした。次の手順に移ります

<手順3> シマンテック関連のフォルダとシステム一時ファイルの削除

まずは「Program Files」内の不要ファイル削除。
C:\Program Files\Norton
C:\Program Files\Symantec
C:\Program Files\Common Files \Symantec Shared

僕の場合64BitのOSのため、「C:\Program Files (x86)」のところにNorton関連フォルダがありました。
「Norton Internet Securit」というフォルダと、「NortonInstaller」フォルダがあったので削除しました。

つぎにユーザのディレクトリ内をチェックしました。
C:\Users\[ユーザ名]\AppData\Local
C:\Users\[ユーザ名]\AppData\LocalLow
C:\Users\[ユーザ名]\AppData\Roaming

参考にしたサイトは、WinXPのようだったので、Win7に適当に読み替えました。
「ユーザ名」については、Default、 UpdatusUser、自分のユーザ、の3つのディレクトリ内をチェックしました
僕の場合、Norton関連のフォルダはありませんでした。

%temp% フォルダ内のファイルを全て削除

参考にしたサイトでは、Tempフォルダ内のクリアを行っていましたが、僕は割愛しました。
Tempフォルダ内は他のアプリでも使っていると思うし、Tempフォルダ内にファイルが残っていてもOSの動作に影響ない、と判断しました。あと古くなったファイルはOSが自動的に削除してくれた気がするので、ほっといてもよい。

この時点では、「コントロール パネル」-「プログラムのアンインストール」の一覧にNortonがのこったままです。

<手順4> レジストリに残った symantecフォルダ を削除する

まず、レジストリの変更は危険なので、バックアップを取得してください
Windows XP でレジストリをバックアップおよび復元する方法

「スタートボタン」-「プログラムとファイルの検索」のところに、regedt32と入力し、サービスの一覧を開きます。
以下の2つ削除することになります。
HKey_local_machine\software\symantec
HKey_current_user\software\symantec

symantecフォルダを選択し、「削除」を選択し、レジストリ削除します。

<手順5> プログラムの一覧から削除する

レジストリ削除した後、「コントロール パネル」-「プログラムのアンインストール」からNortonInternetSecurityを右クリックして、アンインストールを実行します。
すると、「存在していないようです~~」といった感じのメッセージが出て、「NortonInternetSecurityを一覧から削除しますか」と聞かれます。削除してOKと答えると、プログラムの一覧からNortonInternetSecurityがなくなりました!!

<手順6> PC再起動して、ウィルスソフトインストール

ウィルスバスターをインストールしようとしたら、「PCに対する変更を反映するためPC再起動してください~~」といった趣旨のメッセージが出て、インストールがキャンセルされた。

なので、PC再起動してから、もいっかいウィルスバスターのインストールをやってみたら、うまくできました。

やれやれ。
直すのに、半日(午後ずっと)かかったよ(涙)

Androidアプリ開発でSQLiteへデータ保存するときのTips

androidのGPSで取得した位置情報を、ローカルのデータベース(SQLite)に保存してみたときに、ちょっと悩まされたので、基本的なところをメモ。

保存したい内容は次の3つ

◆時刻(GPS情報取得した時間)
◆経度
◆緯度

今使ってる開発環境
AndroidSDK r20.0.3
Eclipse IDE for Java EE Developers_ Juno (4.2)64Bit版


(1)テーブル設計
まず、SQLiteで使用できるデータ型はどうなっているかというと、

INTEGER 符号付整数
REAL   浮動小数点
TEXT   テキスト
BLOB   バイナリデータ
NULL   NULL

Date型がないので、時刻として、「1970/1/1 00:00:00 UTC からのミリ秒」を使うことにする。SQLiteには、INTEGER型で保存。
経度・緯度については、小数点が含まれるため、SQLiteにはREAL型で保存。
また、主キーとして、「id」カラムをつけておく。
テーブル作成時のSQLは、以下のような感じになった。

        private static final String CREATE_TABLE_SQL =
          "create table gpsRawData"
          + "(id         integer primary key autoincrement,"
          + " dateMillis integer not null,"
          + " latitude   real    not null,"
          + " longitude  real    not null"
          + ")";
          :  :  :
      (以下省略)

(2)データ投入

データinsertするやり方としては、ContentValuesを使うやり方、SQLiteDatabase.execSQL()、の2通りあるらしい。

execSQLは、SQL文をそのまま実行できる。ただし、insert、update、deleteの時にしか使えない。(検索(select文)をしたいときは、rowQuery()メソッドやquery()メソッドでできるらしい)

SQL文をEclipseが構文チェックしてくれない気がするので、今回は、ContentValuesを使うことにした。
コードは以下のような感じになった(lat、lotは、それぞれ緯度、経度の値が入っています)

        // DBへデータ保存
        DatabaseHelper dbhelper = new DatabaseHelper(this);
        SQLiteDatabase db = dbhelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put("dateMillis", mStartTimeMillis);
        values.put("latitude", lat);
        values.put("longitude", lon);

        try {
            db.insert("gpsRawData", null, values);
        } catch (Exception e) {
            Toast.makeText(this, "データの保存に失敗しました", Toast.LENGTH_SHORT).show();
        } finally {
            db.close();
        }

(3)データ検索

SQLで言うところのselect文を実行したいときは、SQLiteDatabaseの、rawQuery()メソッドやquery()メソッドで行う。
rawQueryメソッドはSQL文をそのまま実行できるとのこと。

で、query()メソッドの書き方を見てみると、

Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)

groupByとか、orderByってところで、条件指定できる模様。ただ、where句が無さそう。
今回の場合、時刻で条件を指定したいと思っている。「12:00~今」といった感じの条件をwhere句で指定したい。
なので、rawQueryメソッドを使うことにした。

コードは以下のような感じにした。
str_fromDateに昔の時刻が入っていて、過去の○時○分から現在までのデータを取得しています。
きちんとデータ取得できているか確認するために、ログにデータを表示させています(Log.dのところ)

        // DBからデータ読み込み
        DatabaseHelper dbhelper = new DatabaseHelper(this);
        SQLiteDatabase db = dbhelper.getReadableDatabase();

        String str_sql = "select * from gpsRawData where dateMillis > " + str_fromDate;

        try {
            Cursor c = db.rawQuery(str_sql, null);

            while( c.moveToNext() ){
                Log.d("result",":" + c.getLong(1) + " " + c.getDouble(2) + " " + c.getDouble(3));
            }

        } catch (Exception e) {
            Toast.makeText(this, "データの検索に失敗しました", Toast.LENGTH_SHORT).show();
        } finally {
            db.close();
        }

---------------
12/15追記
上記のソースコードの、ミスプリ修正しました。
「時刻、緯度、経度」をログ出力しているところの、引数が違っていました。

Log.d("result",":" + c.getLong(0) + " " + c.getDouble(1) + " " + c.getDouble(2));
Log.d("result",":" + c.getLong(1) + " " + c.getDouble(2) + " " + c.getDouble(3));

---------------

(4)SQLiteの操作

Android Debug Bridge (adb)をつかって、SQLiteに接続(ログイン)できる。
これで、直接DBのテーブルの中身を見ることができる。テーブルが作成できているか、データが保存されているか、直接確認できる。

Androidエミュレータが起動している状態で、Windowsのコマンドプロンプトから、「adb shell」を実行する。そうするとコマンドプロンプト「#」が返ってくる。

 C:\~\~>adb shell
 #

(adbにパスが通っていない場合は、以下の場所にあるadbを直接実行するか、Pathを通してください。
C:\[AndroidSDKインストール先]\android-sdk\platform-tools )

cdコマンドでディレクトリ移動して、lsコマンドでデータベースを確認します

 # cd /data/data/[パッケージ名]/databases
 cd /data/data/[パッケージ名]/databases
 # ls
 ls
 [DB名].db

sqlite3コマンドでデータベースに接続します。

 # sqlite3 (データベース名)
 sqlite3 (データベース名)
 SQLite version 3.5.9
 Enter ".help" for instructions
 sqlite>

ここからさらに以下のコマンドで、テーブル一覧とテーブル定義をチェックできる。

「.tables」 テーブルの一覧表示
「.schema [テーブル名]」 テーブルの定義を表示

テーブル内のデータは、SQL文で見る

「select * from [テーブル名];」

Androidアプリ作ってみたら、activityの数だけ起動アイコンできたんですけど

設定画面にPreferenceActivityを使うと、設定した内容を覚えててくれる。(アプリを再起動したとき、前回設定した状態になってる。)
PreferenceActivityといいよ、ってことで使ってみた。

設定画面はちゃんと動いたんだけど、よくみると”設定”っていう名前のアイコンができてた。なにこれ。

ためしにクリックしてみると設定画面が起動する。いらねー、このアイコン。


で、結局、マニフェスト(AndroidManifest.xml)の書き方が原因でした。

<intent-filter>タグの中身を、コピペしていたんだけれど、これを消したら、アイコン出なくなりました。

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

最終的に、マニフェストの中にはこんな感じでactivityを追加しておいた。

        <activity android:name=".AppPreferences"
            android:label="@string/menu_apppreferences"
            android:launchMode="singleTask" >
        </activity>

11/5追記

その後わかったんだけれども、あえて複数のActivity起動アイコンを表示jさせておくこともあるらしい。
たとえば、動作確認・テスト用の画面(Activity)を用意しておき、それを起動するアイコンを表示させておく。
そうすることで開発期間中のテストが簡便になるみたい。
(アプリを公開するときは、テスト用のActivityを非表示にするのを、忘れないようにしないといけない。)

BloggerからWordPressへの移行メモ

Bloggerを使い始めた矢先に、wordpress.comへの移行を決意しました。
Wordpressのインポート機能に、BloggerからのImportがありますが、画面の形が崩れることがあるらしいので、別のツールで変換することにします。

(参考) 埋め込んだリンクなどが、正常に表示されない状態、乱れた状態でインポートされることがあります。
【Tips】BloggerからWordPressへの移行。【WordPress】 | TAKA@P.P.R.S TECH!!!!


(1)Bloggerのデータをエクスポート
Bloggerの管理画面で、[その他]-[ブログをエクスポート]を選びます

ダウンロードをクリックすると、blog-mm-dd-yyyy.xml が送られてきます。

(2)データ変換
Blogger2Wordpress conversion utility というサイトに行って、データ変換します

[ファイルを選択]のところに、Bloggerからエクスポートしたファイルを指定し、[Convert]をクリック
wordpress-wxr.xmlというファイルがダウンロードされる

(3)Wordpressにインポート
Wordpressの管理画面から、[ツール]-[インポート]を選択

今回は、すでにWordpress向けに変換済のデータをインポートするので、
インポート画面で”WordPress”をクリック

ファイルをアップロード

僕の場合、Bloggerアカウントと、Wordpressアカウントの名前が違ったからなのかもしれませんが、アカウントの変換名を聞かれました。

インポートが始まります。
終わったらメールが送られてきます

僕の場合、ブログデータは少ししかなかったのに、インポート終了まで、すごい時間がかかった。30分くらいたっても「処理中」になっていたんで、あきらめて寝た。

今になって思うと、xmlファイルの中にブログの画像とか入ってるんだろうか。wordpressがネット経由で、自分で取りに行ってるのかな。

AndroidエミュレータにGPS現在地を送信する

AndroidアプリでGPSをつかうものを作ってみたので、実機でテストしてみた。
が、家の中だとGPS情報取得できなくて、いちいち外に出ないといけなかったりする。
めんどくさー、と思いつつもそんなことしていたけど、実はEclipseからGPS情報を送信できました・・・。

というわけで手順をメモ


バージョンが違ってると、けっこう見た目が変わってくるみたいなので、自分のを書いときます
Windows7(64Bit)
AndroidSDK r20.0.3
Eclipse IDE for Java EE Developers_ Juno (4.2)64Bit版

(1)Eclipseの、DDMSパースペクティブを開きます
僕の場合、一度DDMSを開いたことがあるので、DDMSアイコンが出ていますが、初めての場合はこちらから。

DDMSを選択

(2)Emulator Controlを開く

複数のAndroidエミュレータを起動している場合は、左側にあるDevicesタブの中からどれか一つ選択します。

そのあと、右側にあるEmulator Controlタブを開きます。するとそこにLocation Controlというのがあります。

(3)GPS位置情報の送信
とりあえずGoogleMapで、新宿の経度・緯度を調べてみました。

で、その値を、Location Controlに入力して送信すると、

新宿に移動できました!


ちなみに、DDMSのカメラアイコンをクリックすると、

スクリーンキャプチャできる。

携帯の実機でテストしているときは、これでキャプチャできる。

AndroidManifest.xmlに記載するandroid:labelについて。

僕が使用しているAndroidSDK r20.0.3では、アンドロイドアプリのプロジェクト作成すると、AndroidManifest.xmlの中にandroid:labelが2ヶ所設定されています。
<application>タグと、<activity>タグの中にそれぞれ設定されています。

アプリの名前を変えようとして、ちょっとだけハマったので、それぞれの意味合いについて、調べてみました。
結論からいうと

<application>タグのandroid:label、android:icon
「Settting」‐「Applications」‐「Manage Applications」で表示されるアプリ一覧に表示される

<activity>タグのandroid:label、android:icon
Androidデスクトップに表示されるアイコンに表示される

(参考)プロジェクトのファイルとxmlとリソース – 愚鈍人


ためしに、AndroidManifest.xmlの中を次のように設定してみました。
icon、labelに、それぞれ別の値を設定しています

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:icon="@drawable/ic_home"
            android:label="@string/title_activity_main"
            android:screenOrientation="user" >

res/values/strings.xmlには、次のように設定してあります

    <string name="app_name">app</string>
    <string name="title_activity_main">act</string>

実際にエミュレータで動かしてみると、

アプリの一覧画面では、配下のような感じ

デスクトップアイコンは以下のような感じ


参考までに、僕が使っている環境はこちらです
Windows7(64Bit)
AndroidSDK r20.0.3
Eclipse IDE for Java EE Developers_ Juno (4.2)64Bit版


11/5追記

Activityを複数作成したときの注意点がありました。
Androidアプリ作ってみたら、activityの数だけ起動アイコンできたんですけど