シンボリックリンクって聞くとセックスシンボルって言葉がちらつく僕は欲求不満なのかもしれない

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
セックスシンボルと言えばやっぱりマリリンでしょ

この記事を三行にまとめると

セックスシンボル……じゃなかった
シンボリックリンクの出番
これがベストな方法かは分からんが……
左からマリリンモンロー、サモハンキンポー、スキヤキベントー、カムチャッカハントーです。

以前、ImageMagickを使ってPDFを画像に変換する方法を記事に書いたことがありました。

まー……あの記事は無駄に長いんで、読むのもめんどうだと思うんですが、その中で、フォントが足りないせいで上手く変換ができない問題が発生したってなことを書きました。

あの記事のこの辺ですかね。

記事を読むのがめんどいって人のために簡単に言うと、ImageMagickを使ってPDFを画像にするにはGhostscriptが必要になるんですが、このGhostscriptは、主に日本語の文字を変換する際に、必要なフォントがサーバーに入ってないと、エラーを出して変換してくれないことがあるんですね。

で、前回はMSPゴシックがないよーって言われて変換できなかったんで、フォントファイルを入れたり何だりして何とか解決したんですが、後日別のPDFを変換したら、別のフォントがないっていうエラーが出た。

正直、このエラーが出るたびにフォントを一つずつ入れてたらキリがない。だからって、最初に使用されると思われるフォントを全部入れるってのも、あまり良いやり方じゃない。フォントなんて大量にあるからね。それこそキリがない。

じゃあどうするかって話なんですけど、実は、Ghostscriptのバージョンがある程度新しいと、自分で何とかしなくても日本語の対応ができてるらしいんですね。少なくとも、バージョン9.07はオッケーみたい。

なーんだ。だったらバージョンアップにすれば、前回もあんな遠回りなことせずに済んだんじゃないのって思うじゃん?

そこなんだよ問題は。

ぶっちゃけ最初から僕は、バージョン9.07をサーバーにインストールしたんですよ。でもどのタイミングでかは分からないけど、ウチのサーバーには9.07の他に8.70っていうバージョンも同時に入っちゃってて、変換を実行すると8.70の方を使って処理するようになってた。だから日本語の変換が上手くできなくてエラーになってたんですね。

まあ、せっかくなんで、そのときの話でも聞いておくれ。お茶飲んで茶菓子でも食べながら聞いておくれ。茶菓子を食べるときは、PCのキーボードがベタベタにならないように気をつけてね。本当は僕がお茶を差し入れられれば良いのだけれど、残念ながらまだ物質を電子転送する技術はないから……ごめん。



実行されるコマンドのパスの違い

前回の記事でも書いたんですけど、PDFを画像に変換する際、ターミナル上(SSH上)で直接コマンドを実行した場合は、エラーが出ずに変換できたんですよ。でもPHPからsystemとかexecを使ってコマンドを実行すると、なぜかエラーが出て変換できなかった。

で、思い立った……というか、よーく調べてみたんですけど、PHPからコマンドを叩いてエラーが出たとき、エラーメッセージはこんなことが書いてある。

Error: /undefined in findresource Operand stack: --dict:8/17(L)-- TT2 1 --dict:5/5(L)-- --dict:5/5(L)-- MS-PGothic --dict:11/12(ro)(G)-- --nostringval-- CIDFontObject --dict:7/7(L)-- --dict:7/7(L)-- Adobe-Japan1 Execution stack: %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1862 1 3 %oparray_pop 1861 1 3 %oparray_pop 1845 1 3 %oparray_pop --nostringval-- --nostringval-- 2 1 2 --nostringval-- %for_pos_int_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- %array_continue --nostringval-- false 1 %stopped_push --nostringval-- %loop_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- %array_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- %loop_continue Dictionary stack: --dict:1155/1684(ro)(G)-- --dict:1/20(G)-- --dict:75/200(L)-- --dict:75/200(L)-- --dict:106/127(ro)(G)-- --dict:285/300(ro)(G)-- --dict:22/25(L)-- --dict:4/6(L)-- --dict:26/40(L)-- Current allocation mode is local Last OS error: 2 GPL Ghostscript 8.70: Unrecoverable error, exit code 1

最後の方で「Ghostscript 8.70」って単語が出てきてる。正直、前回はここまでちゃんとエラーを読み込んでなかったから、完全に見逃してたわ。これに気づいてれば、前回の段階でここに辿り着けていたのに……無念なり。

ってか、もっとちゃんと考えるべきだったんですね。何でターミナル上ではできるのに同じことがPHPからだとできないのかって。コナン君だったら真っ先にそこを疑ってるはずだわ。

何にせよ、僕が使用したいGhostscriptのバージョンは、さっきも出てきましたが、9.07です。

そこで、Ghostscriptを実行するコマンド「gs」のパスはどこなのかってのを、ちょいと調べてみました。コマンドのパスを調べるには「which」ってコマンドを使います。

# which gs

このコマンドを、ターミナル上と、PHPのexecでそれぞれ実行してみると、こんな結果が返ってきた。

//ターミナル
/usr/local/bin/gs

//PHPのexec
/usr/bin/gs

違う結果が返ってきたんですね。どうやらこれが、ターミナル上だと上手く変換できて、PHP上だとエラーが出る原因だったらしい。

これが分かれば、あとは簡単よ。PHPから実行したときも「/usr/local/bin/gs」が実行されるようにすれば良いじゃねーかって話よね。



これがベストな方法かは分からんが……

そこで、セックスシンボル……じゃなかった、シンボリックリンクの出番ってわけです。

正直、セックスシンボル……ああいや、シンボリックリンクっていうものの存在自体は前々から知っていたんですけど、実際にそれを活用したことがなかったんで、意味はよく分かってなかったんですよね。セックスシンボルの方はもう、大人の階段を上り始める前からしっかりと意味を把握しておりましたぞ。

環境変数とかいうのを変更しても良いみたいなんですけど、そっちはそっちでよく分かんなかったし、今回はこのセッ……シンボリックリンクの設定で何とか解決できたので、それで行ってみましょー。

ま、やることは簡単です。コマンドを一行実行するだけ。

# ln -sb /usr/local/bin/gs /usr/bin/gs

これだけです。「ln」っていうコマンドはリンクファイルを作成するコマンドで、シンボリックリンクを作成したい場合には、オプションに「s」つける。「b」は、リンクの生成先にすでにファイルが存在する場合に、バックアップを取ってくれるオプションです。一応念のためにね、僕もこのコマンド使うの初めてだったから、bをつけておきました。こういうのつけておくのは大事ですよ。シンボリックリンクじゃなくて、あっちの方もね。いざ実行するときにはつけるものつけるじゃない? 「g」をつけるものじゃない?

シンボリックリンクっていうのは、んーと、そのリンク先のファイルが、リンク元のファイルと同じように扱える仕組みというか、何かそんな感じです。

例えば、今「sample1.php」っていうファイルがあったとして、「http://norm-nois.com/sample1.php」っていうURLでアクセスできるとしましょう。sapmle1.phpは、シンプルに「hello world」を表示するファイルだとして、今sample1.phpのシンボリックリンクをsample2.phpに作成した場合、「http://norm-nois.com/sample2.php」にアクセスすると、同じように「hellow world」が画面に出力されるって感じです。説明が分かりづらいかしら?

//sample1.phpの中身
echo 'hello world';

//シンボリックリンク作成
# ln -s sample1.php sample2.php

//http://norm-nois.com/sample2.phpにアクセス
hello world

gsコマンドの場合もこれと同様で、PHPのexecでgsコマンドを呼び出すと「/usr/bin/gs」が実行されるわけですが、シンボリックリンクを作成することで、これは「/usr/local/bin/gs」を実行するのと同じになるってことですね。だからターミナル上で実行する場合と同じになって、Ghostscriptのバージョンも9.07の方を使用してくれるようになる。

SSH上で実行してもエラーが出るって場合はまた話が別ですけど、SSHの方は正常に変換できるのに、PHPから実行するときだけエラーが出るって場合は、たぶん僕と同じ状況になってる可能性が高いので、まずはバージョンを確認してみて、シンボリックリンクを作成すれば、解決できるかもしれません。

それにしても、どのタイミングで8.70と9.07が混在しちゃったんですかねー……ImageMagickを入れるときに、ついでに入っちゃったりしたんですかね。
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください