Applesouichirou0はてブ!1ツイート0FB0Pocket0google+普段は鉄道もバスも乗らないのでICカード乗車券を持ち歩くこともなかったのだが、たまに利用する際に小銭を用意しないといけなくなるので、1枚だけICカード乗車券を買ったことがる。1,000円だけ入れておいて必要なときにはそのカードを使う。残高が減ってきたらチャージする。仕事の日と休みの日では財布が違うので、カードを移してないときは現金で払う。カードを使うことに面倒を感じていた頃にiPhone7が出てSuicaでの対応が可能になった。スマホは常に持ちあるいているので、急にバスを利用することになっても大丈夫だし残高が減ってきてもApplePay経由でチャージできる素晴らしく便利。財布要らずでコンビニにちょっと買い物いけるし。昨日久しぶりにコンビニでSuicaを使った際に、2,336円の表示があって『シャリーン』と音がして店員さんも「はい大丈夫です」と言われたのに金額表示が変わってないことに気がついた。使った直後は通知が表示されるのにそれも表示されない。利用履歴は直ぐに反映されないので後ではっきりするかと思ったけど気になってSuicaアプリの明細を見てみると2週間前に使ったときから残高が反映されていないことが分かった。正解だったWalletの方のSuicaの情報を確認しても同じ状態アプリを立ち上げなおしても、iPhoneを再起動しても変わらなかった。いじっているとApplePayでSuicaの情報を表示させて『ヘルプモードをオンにする』を押したあとにSuicaアプリを立ち上げると金額が更新されることが分かった。最後の260円は10日前に使ったときの分やっぱり通知も残高更新も止まっていたことが分かる。更新されたしよかったよかったと安心したけど、Suicaを使うとやはり同じ現象が起こってしまっている。不具合souichirou0はてブ!0ツイート0FB0Pocket0google+先の投稿でcomposerのアップデートでコマンドが通らないときの対処法を書きましたが、今度は更新途中でこけてしまう場合の対処法です。skipping.とあります。zipとunzipコマンドが通らないよ。これも、いくつかサーバを管理していると入れていないパッケージがあるときに起きてしまいます。unzipインストールが終わったら再度composerの更新コマンドを叩きます。update今度こそ正常に更新が流れます。不具合souichirou0はてブ!0ツイート0FB0Pocket0google+いくつかサーバを管理していると、予期せぬタイミングでコマンドが通らないサーバが出て「???」と迷ってしまいます。今日はcomposerのアップデートでコマンドが通りませんでした。18:23:41composerとだけ叩いて色々出てくればcomposerはインストールされています。いうことは、アップデートコマンドが通らないのは単純にパスが通っていないためです。Composer入れたときは何かしら作業しているので、その時にコマンド叩いているはずなのに何故今になって通らないだろうという疑問は捨てます。動かないものは動かないのです。composer.pharをパスが通る位置に配置すればOKです。動画変換souichirou0はてブ!0ツイート0FB0Pocket0google+カメラの性能も上がり、4Kサイズで撮影できるビデオも普及し始めました。720スマホやタブレットで見るならHDサイズでも十分耐えうる解像度です。ブルーレイに焼いて綺麗に見たいという人もいるでしょうが、大多数の人が望んでるのかなと強いて言えば、動画編集(フルHDサイズ)する際に4Kサイズだからこそ部分的な拡大をしても画質が荒れないというメリットは大きいです。動画編集をする際に4Kサイズのメリットに助かる場面などほぼなく、無駄に容量が大きく編集作業も時間が掛かるというデメリットの方が大きくなってしまいます。それでも撮影時は4Kサイズで撮っておきたいですよね。Encoderを使って一括で動画のサイズを小さくできますが、なんたって高価です。そこで、FFmpegを使ってバッチ処理で一括でリサイズしてしまいましょう。FFmpegのインストールは前回の記事を参照してください。今回もデスクトップ上に『movie』というフォルダを作って、その中で動かします。2.19GBのファイルもありますね。このファイルの記録時間って5分程度なんです。30分回し続けると15GBぐらいいってしまいます。次はシェルスクリプトファイルを作ります。あるのがサイズ変更のコマンドです。横幅や高さに合わせてアスペクト比キープできるで、サイズ変更には便利なコマンドです。今回は横を1920と指定して、高さはアスペクト比キープで調整されています。気をつけないといけないのが、幅が1920以下のファイルが存在しているとサイズを拡大することになってしまいます。画質が粗くなることになりますのでファイルの設置時には気をつけてください。ffmpeg_sizedown.shファイル分だけ処理がループします。完了したフォルダを見るとファイルの容量がかなり少なくなったのが分かりますね。95MBになています!驚異的な容量削減です。画質は落ちますが、編集時にはこのファイルを使うとエンコード時間が減るので助かります。4Kサイズでないとダメな部分には4Kサイズを使用して、その他は書き出しサイズに落としたファイルを使うほうがよさそうです。「この部分はタイムラプスの分と入れ替えて」と要望が入り、「タイムラプスで撮った分あったっけ?」となる。カメラのタイムラプスモードで撮っていなければ、その動画はもちろん普通の動画である。再生速度を上げて変換すれば30分を2分以内にすることなど容易いが、所詮早送り状態なのでタイムラプスにはほど遠い。そこでFFmpeg(エフエフエムペグ)の登場ここではMacを元に説明するが、コマンドはWindows版でも同じです。【MacにHomebrewをインストール】MacBookProにFFmpegをインストールしますが、先にHomebrewをインストールします。HomebrewとはMacOS用のパッケージ管理システムで、コマンドを打つだけでMacOSに様々なソフトウェアやライブラリをインストールでき、更新もコマンドで簡単にできるようになるものです。「なんだか難しそう」と私も初めは思いましたが、入れてみるとすっごく簡単で便利に使えるようになります。https://brew.sh/index_jaHomebrewをインストールするにはXcodeがMacにインストールされていなければいけません。Xcodeをインストールするのはかなり重いですがここは頑張るしかありません。Xcodeのインストールが終わったらMacのターミナルを起動します。起動したら下記のコマンドを流します。https://raw.githubusercontent.com/Homebrew/install/master/install)"少し時間が掛かるので画面が固まったように感じますが、じっと待っているとパスワードを聞かれます。このパスワードはMacにログインしているユーザーのパスワードを入れます。インストールが終わったら、下記のコマンドを打って確認します。2018-09-17)【MacにFFmpegをインストール】Homebrewのインストールが終わったらFFmpegをインストールします。ffmpegこれだけでインストール完了です。確認のために下記のコマンドを打ってみます。ヘルプがずらっと表示されますが一番上を見てみるとバージョンが表記されています。1.100これでFFmpegの準備はできました。普通に撮った動画をタイムラプス風に変換してみましょう。【FFmpegで動画を変換】FFmpegはマンドラインで操作する必要がありますが、基本を覚えれば難しくありません。方は難しく感じられると思うので、基本形をお伝えすることにします。・Macのデスクトップに『movie』というフォルダを作成しましょう。・『movie』フォルダに変換したいファイルを置きます。上書きしてしまうと元のファイルが消えてしまうので元のファイルは別の場所に保存しておきましょう。ターミナルを再度立ち上げて、下記のコマンドを打つと対象のフォルダまで移動できます。変換後のファイル名.mp4音のテンポを倍速に合わせて変更しています。atempoは2.0までしか設定できないので、繋げた分だけ掛け算となります。暗号化souichirou1はてブ!0ツイート0FB3Pocket0google+mcrypt関数はPHP7.1.x系より非推奨、PHP7.2.x系より廃止となりましたので現在推奨となっている『OpenSSL関数』で文字列の暗号化と復元をする方法を紹介します。//暗号化・復元用のソルトを指定します。'東京都港区南青山2丁目';//暗号化・復元用のソルトを指定します。$iv);ここで暗号化は完了ですが、復元させるためにデータベースに保存する項目はIVキーと暗号化されたデータとなりますIVキーとは『単に暗号化ルーチンに異なる初期値を与えるためだけのもの』ということで、一緒に保存して構いません重要なのはパスフレーズの方です。//暗号化したときのソルトを指定。base64_decode($base64_encrypted);//暗号化したときのソルトを指定。迷惑メール対策souichirou1はてブ!1ツイート0FB2Pocket0google+WEBサイトにメールアドレスを素のままで記載するとSPAMメールのアドレス収集ロボットに集められてしまうので色々と工夫しますよね。迷惑メールが増えてしまうと大事なメールを見落としていまう確率があがってしまいます。対策してよくあるのは・@マークを全角にする・@マークをHTMLエンティティ化(【@】にする)・メールアドレス自体を画像にして表示するどれも利用者に不便をかけたり、煩わしかったりします。画像以外はクローラーが対策をすれば収集するのは簡単ですしね。『クリックしたときにメールソフトを起動させてすぐにメールが送れるようにしたい。』そんな場合にJavaScriptを使ってサイトソースにメールアドレスを残さない方法です。記述は要素がないときにJavaSciptがエラーを起こさないようにするために要素の有無をチェックした上で動作するようにしています。atob(obfuscateStr));$(obfuscate).html(atob(obfuscateStr));}});/*if($(obfuscate).length){}の記述は要素がないときにJavaSciptがエラーを起こさないようにするために要素の有無をチェックした上で動作するようにしています。*/メールアドレスを表示させるアンカータグの記述にあるdata属性(data-obfuscatekey)にbase64形式にエンコードしたアドレスを入れます。JavaScriptで該当の要素にあるdata属性(data-obfuscatekey)の値を取得して、atob関数でbase64形式でエンコードされたデータの文字列をデコードします。exsample.com”と置き換えられます。最後にリンクテキストにデコードしたメールアドレスを書き換えています。ソースコードを見てもbase64形式にエンコードされた文字列しか残っていませんのでクローラーもメールアドレスとは判別するのは難しいでしょう。data属性の値をデコードしてメールアドレス形式だったら収集するクローラーが出てくる可能性もあります。複雑にしたい場合はメールアドレスを分割し、data属性を複数持たせておいてデコードしたものを繋ぎ合わせればいいだけです。監視souichirou1はてブ!0ツイート0FB2Pocket0google+WEBサーバの死活監視の1つとして有効的なのがURLチェックです。PINGコマンドでドメイン名を指定してもサーバ側(FWなども含む)でPINGに応答しないように設定していると稼動しているのに応答がないといった状況になります。1番正確に判定しやすいのが、実際にURLにアクセスして目視する。1日に何度も目視なんてしてられませんから自動で監視してくれるサービスもあります。大きな企業になれば自動で監視してくれるサービスにも費用を出して万全の体制がとれますが、あまりお金を掛けられない会社では担当者が毎日WEBサイトにアクセスして死活監視を目視しているということがあります。監視サービスを利用していても、エラーが発生した場合に複数人にEメールメッセージは送信されているが「誰か対応するだろう」といった対応漏れが発生してしまうことも起こります。Eメールだと他のメールに埋もれて見落としてしまったり、自動メール配信なので迷惑メールとして判定されてしまったりとリスクがあります。そこで、お金をかけずに複数人でも進捗が把握できるようにチャットワーク(https://go.chatwork.com/ja/)を利用する仕組みを考えました。・Cron・チャットワークのアカウント(API専用で用意した方がいいです)※チャットワークについてはこちら(https://go.chatwork.com/ja/)【確認できること】ブラウザからHTTP(S)接続してページが見えるかどうかHTTPアクセスを強制リダイレクトでHTTPSにしているなどアクセス左記がリダイレクトされていてもHTTPステータスコード302が返ってきますので正常稼動していると判定します。SSL証明書の失効、設定ミスの場合はアクセスが拒否されますのでエラーとして判定されます。ログイン画面が表示されるものは正常稼動と判定されますが、Basic認証の場合はエラーとして判定されます。グローバルIPでHTTP接続が可能ならば正常として判定されます。サーバの応答が異常に遅い場合(応答の状態にもよりけり)もエラー判定されます。・監視したいサービス名称を決める際は2バイト文字・半角カナ・記号等は避けてください。サーバは稼動しているけども負荷が高くて応答に時間がかかっている場合も分かるように応答時間をシビアに設定しています。項目を変更してください。//監視したいサービスを追加します。//エラー結果を保存するファイルのファイル名に使用しますので2バイト、半角カナ・記号等文字は使用しないようにしましょう。"{$targetName}はエラーです。"{$targetName}は正常({$resultHttpCode})です。"エラー発生!メッセージ送信の処理に移行します。"ファイル({$errorFileName})が存在しないので新しく生成します。"エラー発生!メッセージ送信の処理に移行します。"<strong>エラー情報用のファイルが生成できませんでした。/>サーバの書き込み権限を確認してください。"{$now}:\n{$targetName}({$targetUrl})で監視エラーが発生しました。\n確認してください。"チャットワークAPIを使用してメッセージの送信が終わりました。"<strong>チャットワークAPIの設定が間違っているようです。</strong>メッセージが送信できませんでした。}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183<?php//監視したいサービスを追加します。サービス名称,対象URL//エラー結果を保存するファイルのファイル名に使用しますので2バイト、半角カナ・記号等文字は使用しないようにしましょう。"{$targetName}はエラーです。"{$targetName}は正常({$resultHttpCode})です。"エラー発生!メッセージ送信の処理に移行します。"ファイル({$errorFileName})が存在しないので新しく生成します。"エラー発生!メッセージ送信の処理に移行します。"<strong>エラー情報用のファイルが生成できませんでした。/>サーバの書き込み権限を確認してください。"{$now}:\n{$targetName}({$targetUrl})で監視エラーが発生しました。\n確認してください。"チャットワークAPIを使用してメッセージの送信が終わりました。"<strong>チャットワークAPIの設定が間違っているようです。</strong>メッセージが送信できませんでした。/>\n";}curl_close($ch);}任意のファイル名でスクリプトを設置したらブラウザからアクセスしてみてください。://example.com/hoge.php全てが正常であれば架空のサブドメインを追加してみてください。エラーがでてチャットワークで指定したチャットルームにメッセージが届けば成功です。JavaScriptsouichirou0はてブ!0ツイート0FB0Pocket0google+TwitterのAPIを使ってデータ取得し、JavaScript経由で処理をしているときにはまった話です。特例の文字列に関するTwitterユーザーをユーザー検索APIで叩いて数名の候補を一覧表示して、その中から目的にあった1人のユーザーをリスト化していくという作業をしていました。users/search詳細:https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-searchTwitterユーザーを一意にする情報としては”screen_name”もしくは”id”本来の目的からいくと”screen_name”が欲しかったので、この時点で取得した”screen_name”を保存していこうかと考えていましたが、Twitterのアカウントは使われていなければ自由に取得することが可能なため、悪意のある取得であったり、偶然のバッティングが発生することもあります。これから将来的には、必要性の高い”screen_name”は入替の可能性も出てくるかもしれません。そこで、書き換えの可能性があり得る”screen_name”だけを取得するよりもユーザー”id”を基準として取得しようと考えたわけです。データの一意性はID(数値)だね。いうことでJavaScript経由でデータベースに保存しようとしていたので、文字列である”screen_name”にエスケープが必要な文字が入っていると面倒だなとも考えたのも1つです。users/lookup)を叩いて”screen_name”を取得するといった流れで作りこみました。送信ボタンにセットした値はこんな感じです。onclick="func_twitterId(ユーザーID)">ID登録処理</button>すいすいと処理を進めていっていると、DB保存前の段階で”screen_name”が取得できなかった場合のエラー処理コードが表示されました。1件飛ばして進めていると、また同じエラーコードが表示されました。IDが取得できていなければ先に進めないようにしていたし、ソース表示してもちゃんとIDがデータとして渡されるようになっている。エラーがでている対象をよく見てみると「IDの桁が多い」ということが分かりました。JavaScriptは『IEEE754』という規格に従って内部的に数値を『64ビット倍精度』で保管しています。うまい表現が見つからないですが、処理できる値に限界があるって感じです。数値だけでIDが構成されているので桁数が増えていっているのでしょう。限界を超えてしまったものをどうするかというと、toFixed(0)を使えばうまく処理できました。getID.toFixed(0);こうすれば数値としてPHPスクリプトに渡して再度APIを叩けば正確な”screen_name”を取得することができます。送信ボタン自体に埋め込む時点で文字列に変更しました。onclick="func_twitterId('ユーザーID')">ID登録処理</button>文字列として最初から処理してしまえばTwitter側の仕様が変わっても問題ありません。これで解決JavaScriptで演算するときは数値の変化に気をつけていましたが、受け渡しでも気をつけておかなければならないことを見落としていました。