ImageMagickコマンドの注意点

こんにちは。イメージマジック三浦です。 2019年が後半に入りました。あっという間に半年過ぎたとも、まだ半年あるんだなとも思います。 今回は「ImageMagickコマンドの注意点」と題して書きます。
業務で、WindowsOSに導入することを念頭に ImageMagickコマンドを調査しましたが、その時に気づいたことを書いてみます。

ImageMagickとは

画像の変換や表示、内部情報などを見るソフトウェア群です。詳しい説明は他のサイトを参照してください。
 https://imagemagick.org/index.php 

インストールについて

ImageMagick開発元が、様々なOS向けにインストーラを提供しています。
特にWindowsOS用では、インストーラ方式のものと解凍して配置するだけのものがありますが、今回はWindowOS向けのポータブル版を使うことにしました。 ImageMagickコマンドの動作には、VC2013再頒布可能パッケージのインストールが必要とされています。最初のパッケージの後に、更新版が出ていますので、導入が必要だとすれば更新版の方がよいかと思います。
(VC2013再頒布可能パッケージ)
https://www.microsoft.com/ja-jp/download/details.aspx?id=40784
(VC2013再頒布可能パッケージの更新版)
https://support.microsoft.com/ja-jp/help/3138367/update-for-visual-c-2013-and-visual-c-redistributable-package
ただし、OSによっては同パッケージをインストールしなくても動いてしまうケースがあるので、実際の画像を使った動作確認は欠かせません。

動作確認をしてみて気づいたこと

WindowsOS向けのポータブル版ImageMagickを動作確認をする中で、ImageMagickコマンドの1つ「convert」が動かないという現象がありました。 以下のようなディレクトリ構成で、
E:\hoge
[D] ImageMagcik
[F] test.psd
PowerShellで、カレントディレクトリをImageMagick直下に移動してconvertコマンドを実行すると、以下のような結果が出ます。
(convertコマンドの詳細は割愛します)。
PS E:\test\ImageMagick> convert ../test.psd[0] ../test.png
無効なパラメーターです - /test.psd
PS E:\test\ImageMagick>
1つ上の階層のディレクトリに「test.png」というファイルができると期待したのですが、エラーになりました。
「convert /?」と入力するとWindowsOSのコマンドのヘルプが出てきたので、ImageMagickの「convert」コマンドを実行するつもりが、WindowsOSの「convert」コマンドを実行していたと考えられます。特に、コマンドプロンプトだと発生しないので、混乱しやすいところです。 PowerShellで期待した結果を得るには、以下のように指定する必要がありました。
PS E:\test\ImageMagick> ./convert ../test.psd[0] ../test.png
または
PS E:\test\ImageMagick> .\convert ../test.psd[0] ../test.png

同じような現象を回避するために

今回のような現象を回避するには、先頭に「.\」を付加してカレントディレクトリのコマンドであると明示する方法が無難だと感じました。「.\」が付いていれば、コマンドプロンプトでもPowerShellでも同じ動きをしてくれるためです。 他には「convert」コマンドが、最新バージョンの1つ前のImageMagick6系と互換性を維持するために提供されるものなので、最新バージョンの「magick」コマンドを使うことが考えられます。

最後に

これから暑くなるので、体調の管理には気を付けてください。
個人的には、睡眠時間の確保と毎日の食事でネバネバ食材を食べることに気を付けていますが、身体が軽くなったように感じているので、これからも続けていきたいと思います。

PowerShellにLinuxコマンドを見る

こんにちは。イメージマジック三浦です。
朝晩の寒さは残りますが、梅の花が咲いているところやプロ野球オープン戦の話題が出てくるようになりました。一方で最近降った雨は冷たかったです。暖かくなるのはもう少し先のようです。

今回のテーマ

今回は「PowerShellでLinuxコマンドを使ってみる」と題して書きます。 かねてより、lsやcurlを起動できることは知っていたのですが、 気になったので正体を調べてみました。

早速試す

実際にPowerShellでコマンドを打ってみると、以下の結果となります。オプションまでLinuxと同じということはないようです。
  • 使える:ls, ls -R
  • 使えない:ls -l
PS C:\hogehoge> ls


    ディレクトリ: C:\hogehoge


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2019/03/01     12:42                subdir
-a----       2019/03/01     12:41              3 aaa.txt
-a----       2019/03/01     12:41              3 bbb.txt
-a----       2019/03/01     12:41              3 ccc.txt


PS C:\hogehoge>
PS C:\hogehoge> ls -R


    ディレクトリ: C:\hogehoge


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2019/03/01     12:42                subdir
-a----       2019/03/01     12:41              3 aaa.txt
-a----       2019/03/01     12:41              3 bbb.txt
-a----       2019/03/01     12:41              3 ccc.txt


    ディレクトリ: C:\hogehoge\subdir


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019/03/01     12:42              6 ddd.txt


PS C:hogehoge>
PS C:\hogehoge> ls -l
Get-ChildItem : パラメーター 'LiteralPath' の引数が指定されていません。型 'System.String[]' のパラメーターを指定し、再
試行してください。
発生場所 行:1 文字:4
+ ls -l
+    ~~
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem]、ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,Microsoft.PowerShell.Commands.GetChildItemCommand

PS C:\hogehoge>

昔からあるWindowsのコマンドは?

ディレクトリ配下の一覧を返すコマンドとして、以前からdirというものがありました。ここでdirを実行してみると、lsと同じ結果が返ってきます。
PS C:\hogehoge> dir


    ディレクトリ: C:\hogehoge


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2019/03/01     12:42                subdir
-a----       2019/03/01     12:41              3 aaa.txt
-a----       2019/03/01     12:41              3 bbb.txt
-a----       2019/03/01     12:41              3 ccc.txt


PS C:\hogehoge>

正体を探る

lsとdirで同じ結果が出るのは判りましたが、何故かはわかりません。これを調べるために、ls のヘルプを見てみます。
PS C:\hogehoge> ls -?

名前
    Get-ChildItem

概要
    Gets the items and child items in one or more specified locations.

…
Get-ChildItem という名前が出てきました。これが正体のようです。
lsを実行すると、「Get-ChildItem」というPowerShellコマンド(コマンドレットと言われます)が実行されます。 dir でも同じ結果が出てきます。
PS C:\hogehoge> dir -?

名前
    Get-ChildItem

概要
    Gets the items and child items in one or more specified locations.

…

「Get-Children」の別名を確認

最後に、「Get-Children」コマンドレットが持つエイリアスを確認してみます。
PS C:\hogehoge> Get-Alias | Where-Object { $_.Definition -eq "Get-ChildItem" }

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           dir -> Get-ChildItem
Alias           gci -> Get-ChildItem
Alias           ls -> Get-ChildItem


PS C:\hogehoge>
ls, dir の他に gci という別名がいることも分かります。

まとめ

PowerShellで「ls」や「curl」が打てた、というところを出発点に調べてみました。Linux系OSで使えたコマンドを試しに打ってみたら実は使える、というものが他にもあるかもしれません。また使えなかったとしても、自分でエイリアスを設定することもできるようです。
スクリプトを作る時は、使おうとしているエイリアスが実行先の環境で設定されているかを確認する必要がありますが、技術的な選択肢の1つの手段として、上手く使っていければと思います。

大量の情報から必要なものを探す(メール編)

こんにちは。イメージマジック三浦です。
昨年、月に1~2回やっているフットサル用に、長袖のトレーニングウェアを買いました。フットサルは屋外でやることが多いのですが、肌が直接外気に触れないだけで体の冷え具合が全く違うので、寒い時期の運動にはありがたい存在です。

今回はメールの中から必要な情報を取り出す、ということをテーマにして投稿します。

【システムからの通知メール】

弊社で運用しているシステムからは、日々多くのメールが送信されてきます。
多くは定時のバッチやタスクが「異常なし」で動作したことを通知してくるメールですが、 時々異常を通知するメールが送信されることがあります。
異常を感知した場合は、内容を確認して必要な対応を取らなくてはいけません。

通知メールは1通ずつ見ていくのが大変なくらいに送信されてきますが、 異常がない時に「異常なし」と通知してもらうことも重要です。「問題なし」の通知を止めてしまうと、異常がなくて通知がないのか何らかの異常で通知できないのか判断しにくくなります。

そこで、送信されてきたメールの中からエラーを通知するメールを取り出すことを考えます。

【キーワードの選定】

ここではシステムからの通知メール本文に
「error: x」(x = 1から9の整数)
という文字列があれば、何かしらの異常があるものと判断します。
異常が1件でも10件でも、「error: 1」という文字列で検索できるということです。

【どうやって抽出するか】

正規表現による検索が使えるメーラーの場合、 上記の規則性をカバーできる正規表現で条件を設定すれば簡単です。 しかし、検索に正規表現を使えないメーラーの場合は悩みます。
※普段の業務ではgmailを利用していますが、gmailは正規表現が使えません。

【実際にやったこと】

gmailでは、必要な分だけOR条件をつなげる方法が使えました。
“error: 1” OR “error: 2” OR … (9までつなげる)
検索条件のテキストを別ファイルに保存しておいて、gmailフィルタのラベル添付機能と組み合わせると、使いやすい状態になりました。

【まとめ】

今回は、大量の情報から必要な情報を探すという観点で書きました。
目の前にある情報をどう整理するかという観点と、どういう情報があれば整理しやすいかという観点の両方を忘れないようにしたいと思います。

コマンドの合わせ技でsymfonyを起動する

こんにちは。10月に入社しました三浦です。

10月22日に弊社の引っ越しがありました。
いくつもの机や椅子を組み立てて、新オフィスでの業務を迎えています。
組み立て中は、別の方が持参した電動ドリルが大活躍しました。
バッテリー切れでヘトヘトになっていたので、持ち主の方から電気をもらっていることを祈ります。

さて本題ですが、今回はsymfonyの起動コマンドをコマンドラインで生成させてみます。
symfonyを自習していた当初、手動でifconfigを打ってIPアドレスを確認してからコマンドに入力していましたが、
何回も打っていたのでIPアドレスを自動で取得できる方法を考えてみました。

今回のテーマ

linux搭載のコマンドだけで、symfony起動コマンドを生成する。

前提条件

以下条件の下で、ホストOSのWebブラウザからsymfonyサイトにアクセスすることを考えます。
1. ホストOS:Windows10、VM:ubuntu18.04
2. 両方ともIPアドレスはDHCPによる自動付与とする。
3. VM上でsymfonyを稼働させる。

ポイント

3の前提より、単にserver:startを実行するだけではアクセスできません。

php bin/console server:start

代わりに、アクセスするIPアドレスとポート番号を明示して起動します。

php bin/console server:start {VMのIPアドレス}:{port番号}

IPアドレスの取得

ifconfigの出力結果から、IPアドレス(XXX.XXX.XXX.XXXの部分)を抜き出してみます。
ここでは、ホストOSと通信できるVM側のNICをeth0とします。

$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet XXX.XXX.XXX.XXX  netmask YYYY.YYY.YYY.YYY  broadcast ZZZ.ZZZ.ZZZ.ZZZ
        inet6 aaaa::bbbb:cccc:dddd:eeee  prefixlen 64  scopeid 0x0<global>
        ether ff:gg:hh:ii:jj:kk  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ifconfigの結果から抜き出すコマンドは以下の通りです。

echo `ifconfig eth0 | grep inet | grep -v inet6 | awk -F' ' '{ print $2 }'` … (a)

symfony起動コマンドの生成

(a)のコマンドを実行して出力されるIPアドレスをシェル変数に格納し、symfonyの起動コマンドを作成します。
なお、ポート番号は8000番を指定しています。

cd {起動するプロジェクト名}
SERVER_IP=`ifconfig eth0 | grep inet | grep -v inet6 | awk -F' ' '{ print $2 }'`
php bin/console server:start ${SERVER_IP}:8000

もう一工夫する

symfony起動中の時に server:start を実行するとエラーになってしまいますので、symfonyが停止中の時だけコマンドを発行するようにします。
今回は、プロジェクトフォルダ直下に「.web-server-pid」がなければ、symfony停止中と判断します。
if文を使って、symfony停止中の判断を追加します。

cd {起動するプロジェクト名}
if [ ! -f .web-server-pid ]; then
  echo `ifconfig eth0 | grep inet | grep -v inet6 | awk -F' ' '{ print $2 }'`
  php bin/console server:start ${SERVER_IP}:8000
fi

これで、IPアドレスを都度取得してsymfonyを起動するコマンドが出来上がります。
別ファイルに保存して適切なパーミッションを設定すれば、ワンタッチでsymfonyを起動するシェルとになります。

最後に

小さいコマンドながら、自分で作れたときは達成感を感じました。
これからも学ぶことは多いですが、今回のような達成感を糧に進んでいきます。