CentOS 7.5上でVagrantとAnsibleを使ってVirsualBoxを操作しようとしたら環境設定に色々ハマった記録。バグトラップな上にグーグル先生が的確な情報出してくれない!!
問題山積み
- VirsualBoxのインストールで失敗する (modprobe vboxdrv が云々)
- secure bootの影響で、署名がないモジュールをロードできないのが原因。署名すればよい。
- だがしかし、署名に使った公開鍵がenrollできない
- mokutilのバグ。1つ前のバージョンに戻す。
- Mac OS X用のVagrantfileとCentOS(Linux)用のVagrantfileではansible providerの名前が異なる
- Mac OS X 用は
ansible
。CentOS用はansible_local
。冪等性とは。 - 参考: Ansible Not Found during Post Provision Task
- Mac OS X 用は
- なんかVagrantfileからは実行できないのに、ansible-playbookでは実行できるんですが… (これは秘密鍵のパスとか、そういう問題かも)
- NFSマウントが失敗する
- firewalldがお仕事してた。vboxnet0をtrusted zoneへ叩き込む(いいのかそれで?)
- "CentOS VirtualBox Vagrant"とかでググると「Vagrantで(WIndowsの)VirtualBoxにCentOSを入れようず」いう話ばかりが出てくるんですよね…。しかし他に適当なキーワードもなく。
各々の対策記録
VirsualBoxのインストールで失敗する
CentOSのおそらく7.4以降~バグ修正版が出るまでは、先に「署名に使った公開鍵がenrollできない」を読んでください。二度手間になります。
RedHatの 26.8. セキュアブート用のカーネルモジュールの署名 が日本語ですし、「何をやっているのか」まで分かってよいです。
単にやるべきことを知りたいだけならば Signing VirtualBox & VMware modules 等があります。 なお、CN=以降はcommon nameを入れるところなので各自考えて置き換えることになります。
例に出ているのは「vboxdrv」だけなのですが、実際は同じディレクトリ内の全ファイルに署名しないとダメでした(全ファイル必要なのかは組み合わせテストが面倒なので確認していません)。
modinfo -n vboxdrv
でこのモジュールファイルのフルパスが出てくるので、そこでパス名から必要なファイルを見つけてください。ちょっとイイ感じにやりたければ ls $(dirname $(modinfo -n vboxdrv) )/* |xargs -l1
とかすればイケるんじゃないかとは思う。
署名に使った公開鍵がenrollできない
問題は、上記でモジュールに署名したあと、その公開鍵を mokutil
へ登録した後で、再起動するとUEFI コンソールで mokutil
にセットしたパスワードを聞かれ、パスすれば以後は公開鍵がOSへ永続登録される、という部分です。何度再起動してもそんな画面出てこないのです…っ
原因は、最新版の mokutil
にバグがあり、肝心のUEFIコンソールが起動しないとのこと。
以下にその説明があります。
元々問題に気付いたのはこのあたりの記事。 "The uefi secure boot bug" の文言を読んだ時の脱力感がハンパない。
Red Hat Bugzilla – Bug 1477735 Shim was unable to measure state into the TPM
対策ですが、バグのない1つ前の mokutil
はCentOSの場合7.3にあります。 http://vault.centos.org/7.3.1611/os/x86_64/Packages/ から mokutil
と shim
のRPMをダウンロードして、最新版を yum remove
で削除後にインストールします。
成功すれば、ブート時にきっちり止まりますので確実に分かります。
この作業前に mokutil
へ鍵を登録したりパスワードをセットしていた場合、その作業からやり直しになるので注意してください。
Mac OS X用とCentOS(Linux)用とのVagrantfile差異
一覧に書いた通りです。Mac OS X 用は ansible
。CentOS用は ansible_local
。このあからさまな違いから見て、CentOS用は何か使い方を変えると ansible
になるのかもしれませんが。
参考記事は以下。
NFSマウントが失敗する
原因がわからないときは、 vagrant ssh
でゲストOSに入ったのち、おそらく画面に表示されているであろうコマンド( mount -o vers=3,udp <ホスト側IP>:<ホスト側Path> /vagrant
等)を実行してみるのがよいです。この際、mount コマンドに --verbose
を追加することで、ある程度情報が増えます。
私のケースの場合 mount.nfs: portmap query failed: RPC: Unable to receive - No route to host
が出ていたので、これは経路が切れてるな…と考えた次第。その後sshでゲスト→ホスト接続を試してみて、接続できたのでfirewallかな、と。
firewall-cmd --add-interface vboxnet0 --zone=trusted
firewall-cmd --list-all --zone=trusted
(確認)
trusted (active)
target: ACCEPT
icmp-block-inversion: no
interfaces: vboxnet0
sources:
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
のような結果になればOK。
発端
gulp-gh-pages を使おうとしたら、以下のような謎のエラー。
node_modules/gulp-gh-pages/node_modules/gift/lib/commit.js:145
ref1 = /^.+? (.*) (\d+) .*$/.exec(line), m = ref1[0], actor = ref1[1], epoch = ref1[2];
^
TypeError: Cannot read property '0' of null
エラー箇所のコードを読むと、gitのcommitログ解析でおかしくなっているように見えるのだけど、なんでcommitログの正規表現処理なんてやっているのかが不明だにゃー、と。
原因
ググると以下のページが見つかったので、取り敢えず gulp-gh-pages-will ではなくて手動で何とかする方法をとってみた。
gulpの「gulp-gh-pages」がエラー履くようになったときの対応
記事内の解説、およびgiftのissueとかを読んでみると、giftの過去バージョンに起因する問題で、gift自体では問題解決済みの版が出ている。しかし、gulp-gh-pagesのpackage.jsonが古いままなので、gulp-gh-pagesとしては問題解決できていない、ということらしい。
どうも gulp-gh-pages 本家もGitHub上では次バージョンのタグが出ていて、最新のpackage.jsonではgiftも最新版使うようになっているので、近々根本的な解決があることを期待したいところ。
なお、gulp-gh-pagesをGitHub版で使えばいいよね、と思ってやってみたところ、今度は gulp-gh-pages が依存する gulp に未リリース・GitHub版を要求され、仕方ないので gulp もGitHub版にしてみたところ、新たな謎エラーが出てしまったというオチがつきましたとさ。
解決手順
"gift": "^0.10.2"
を package.json に追記npm install
実行後、rm -rf node_modules/gulp-gh-pages/node_modules/gift
として gulp-gh-pagesのインストール結果内giftを削除(こうしないと v0.10.2 のほうを使ってくれない)
JavaScriptベースで一通りつついてみたので、実装方法の備忘録。秘密鍵扱うので、クライアントサイドJavaScriptはNGですな。基本的にはプログラミングガイド読めば分かるものです。コーディングはお仕事しますよ? 的な。
必要なもの
- アクセスキーID:
- Amazonアソシエイト・セントラル →ツール →Product Advertising API で取得可能
- 秘密キー:
- Amazonアソシエイト・セントラル →ツール →Product Advertising API で取得可能(認証情報生成時のみ表示されるようなので注意)
- アソシエイトID:
- Amazonアソシエイト・セントラルの右肩に出てるアレです
実装上のポイント
一先ず、ASINで指定した特定商品の情報取得を試しました。
- エンドポイントは固定。シグネチャ生成時にhostとpathに分割することになります。
- クエリは文字コード順でソートすることになるので、& で連結せずに扱ったほうが良さ気でした。ソートはArray.sort()のアルゴリズムで問題ない筈。
- 各所の値は
encodeURIComponent()
でエンコード。 - TimestampはISO形式の日付+時間ですが、ミリ秒以下があるとエラーになりますので
(new Date()).toISOString()
は使用できません。 - シグネチャはbase64 エンコードの HMAC_SHA256です。Node.jsの場合
crypto.createHmac()
が使用可能です。
うっかりハマる点として、各所に出てくるサンプルでのエンドポイントがアメリカ版ですが、日本のAmazonでアカウント登録している場合は日本のエンドポイントを使う必要があります。
処理の流れ
- タイムスタンプを生成します。UTC~メソッド群を使用して、ミリ秒を含まないISO形式の日付を生成。getUTCMonth()が0~11を返すことと、1桁の値は右側に0が必要になることに注意
-
クエリを項目ごとに分割・格納したArrayを組み立てます →query
- AWSAccessKeyId
- アクセスキーID
- AssociateTag
- アソシエイトID
- Operation
- ItemLookup (今回は商品情報取得なので)
- ItemId
- ASIN
- Timestamp
- タイムスタンプ
- エンドポイントURLをバラします。Node.jsの場合
url.parse()
でパースして、hostとpathを使用します。 - クエリをソートし、&で連結しておきます。 →sorted_query
- 'GET', エンドポイントのhost, エンドポイントのpath, sorted_queryを\nで連結し、
crypto.createHmac()
で処理した後digest('base64')
でBASE64形式で取り出し、更にencodeURIComponent()
でエンコードします。 →signature - エンドポイント + ? + sorted_query(queryでもいい筈) + & + signature にアクセスします。後はレスポンスを適宜調理。
リクエスト制限は「1秒に1回」とされているのですが、試行しているときにコード修正で明らかに数秒以上経過してても制限にかかってエラーになったので、もう少し余裕持ったほうが良さそう。
ところでPAAPIってやっぱり「パァイ」って読めばいいんですかね。
data() で初期値を定めるとき、new Date()の値をyyyy-mm-ddにしてやれば万事解決。←結論
細かく解説すると。
- Vue.jsではコンポーネントの data() で初期値セットを返す
- <input type="date" > はvalueとしてISO形式(yyyy-mm-dd)を与えないと初期状態として日付を表示してくれない(値があっても "yyyy/mm/dd" というユーザに大変お優しい表示となってしまう)
- <input type="date" > に new Date() の値をそのままセットしても上記理由によりまともに表示してくれない
解決パターン。
Google Shortener APIで短縮URLを生成する処理をちょっと試してみたのでメモ的に残しておく。
- APIキーは各自Googleアカウントで発行すること
- fieldsクエリは全部乗せになってます
- 正常に実行できると、アラートダイアログで結果が表示されます
- エラー処理? なにそれおいしい?
$(function() { var apikey = <各自APIキーを入力>; var url = 'https://twitter.com/mami_tuchino'; /* これが短縮したいURL */ $.post({ url: 'https://www.googleapis.com/urlshortener/v1/url?fields=analytics%2Ccreated%2Cid%2Ckind%2ClongUrl%2Cstatus&key=' + apikey, data: JSON.stringify({ longUrl: url }), dataType: 'JSON', contentType: 'application/json', success: function(json) { alert(json.id); }, error: function(error) { console.logt(error); } }); });
別売りのELPAの電源タップを取り付けて、複数の方法で固定可能なタップホルダー。
4種類の方法で固定可能です(互いの位置関係が合えば複数の方法で固定も可能)。
- フックで吊り下げ
- マグネットで鉄板に貼り付け
- バンドを巻きつけて固定
- 木ネジで固定
適合タップに制限があるので、そこだけは注意。また、ホルダーと言ってもがっちり固定ではなく、片手で外せる程度の強度です。何かがぶつかるとホルダーから外れてしまう程度。
ググってみると、大抵以下のようなコードが多数見つかる。
ruby -e 'p [*1..9, *"a".."z", *"A".."Z"].sample(8).join'
これ、
ruby -e 'p [*"!".."z"].sample(8).join'
でいいんぢゃねぇです? 文字コード的に半角スペース, "!" , …数字…大文字アルファベット…小文字アルファベット、と続くので。まあパスワードに半角スペース入れると入力が厄介なことになりそうだからその次の "!" から始めるとして。
あ、でも " とか ' とか ` あたりもパスワードに含めると扱いがアレ気になりそうだから、
ruby -e 'p [*"!".."z"].reject {|c| %w"\" '"'"' \`".include? c }.sample(8).join'
くらいで、どうですかね?
地図を表示したり、地図上のあれこれを検索したりする用途のAPIについて、使用条件などをまとめました。なお、2017年6月23日現在の状況ですので今後変わる可能性があります。利用規約等は最新版を確認のうえ、各人の判断にてご利用ください。解釈ミス、情報のもれについて当方は責任を負いません。
サービス名 | 提供される内容(概略) | 利用制限 | 商用利用 | クレジット表記 |
---|---|---|---|---|
https://developers.google.com/maps/documentation/api-picker?hl=ja
|
https://developers.google.com/maps/pricing-and-plans/?hl=ja Google Maps Android API、Google Maps SDK for iOSについては制限なし。ただし「標準プランの利用規約で許可されている」との表記があるので、こちらも要確認。 Google Maps Embed APIについては無制限の無料利用。 地図表示については「1 日あたり最大 25,000 回のマップロードが無料」、Google Places API Web Serviceは「1 日あたり 150,000 回のリクエストが無料(クレジット カードによる本人確認が必要)」。その他のサービスはAndroidおよびiOS向けが「1 日 1,000 件」、Web Serviceが「1 日あたり 2,500 回」までのリクエストが無料。 無料に該当するもの以外は、少ないほうの数(スマートフォン系は1,000、Web系は2,500)で判断したほうが無難と思います。 |
https://developers.google.com/maps/pricing-and-plans/?hl=ja 有料サイトの場合は無条件に有料プランが必要と解釈しています。無料サイトの場合Yahoo!の「~ユーザーから利益を得ていると認められる~」のような言い回しは無いので無料プランで利用可能と思われますが、リクエスト回数の制限が厳しいので実質的に有料プランを選択することになると思われます。 その他「非営利組織、危機対応組織、および報道機関」向けに特別扱いがあるようなので、該当する場合は申請することで無料のまま利用できる可能性があります。 |
地図を表示させた場合は、地図画像自体にクレジット表記が埋め込まれています。 API利用の場合、基本的には「Googleが提供する地図と併用」となっていますので実質的にクレジット表記を表示することになります。PlacesAPI Web Serviceは「Google Places API Web Service のデータを Google マップには表示させず、ページまたはビューに表示するアプリケーションでは、データと一緒に「Powered by Google」ロゴを表示させる必要があります。」とあります。(https://developers.google.com/places/web-service/policies?hl=ja) |
|
Yahoo! |
https://developer.yahoo.co.jp/webapi/map/
| 1アプリケーションIDごとに1日50000回 (https://developer.yahoo.co.jp/appendix/rate.html) |
Yahoo! Open Local Platformの利用方法; 2. YOLPでは、以下に列挙するもののいずれかに該当するとYahoo! JAPANが判断した場合、YOLPのライセンスを消滅させることがあります。 ; YOLPにより提供される情報の使用によりユーザーから利益を得ていると認められるサービス (https://developer.yahoo.co.jp/webapi/map/#policy) 商用利用不可、もしくは多少なりともビジネスで利用する意図があるならば一度Yahoo!へ問い合わせた方が無難と判断します。 有償プラン: YOLP Premier (https://map.yahoo.co.jp/promo/yolp/yolppremier.html) |
Yahoo! JAPANの提供するAPIを利用するすべてのサイトやアプリケーションには、クレジットを表示する必要があります (https://developer.yahoo.co.jp/attribution/) |
ぶっちゃけ技術検証で途中まで書いたのだけど、当面使いそうに無いのでココという蔵に「お蔵入り」です。
必要なもの
- AWS SDK for PHP
- AWSのアクセスコード
サンプルコード
- AWS SDK for PHPはComposer等を使用せずに直接展開、 lib/ 以下に配置しています。Composer使った方が楽ですが、シェルログインできない環境の場合は手作業で配置した方が状況把握できてよいので。
- バケット名は aws-test.logicalrabbit.jp 。予め作成しておきませぅ。
認証
<?php require 'lib/aws-autoloader.php'; use Aws\S3\S3Client; $s3client = new S3Client( [ 'region' => 'ap-northeast-1', 'version' => '2006-03-01', 'signature_version' => 'v4', 'credentials' => [ 'key' => [アクセスキー], 'secret' => [秘密鍵], ], ] ); ?>
オブジェクト一覧の取得
テーブル化して一覧にしています。
<table> <tr> <th>Key</th><th>Size</th><th>Last modified</th> </tr> <?php $result = $s3client->listObjects( [ 'Bucket' => 'aws-test.logicalrabbit.jp', ] ); foreach( $result['Contents'] as $content ) { echo '<tr><td>' . $content['Key'] . '</td><td>' , $content['Size'] . '</td><td>' . $content['LastModified'] . '</td></tr>'; } ?> </table>
オブジェクトの追加
取り敢えず lib/ 内に展開前のaws.zipがあったので、それをアップロードしてみるなど。アップロード成功の有無確認として、ETagを画面に表示します。
<?php $reader = fopen('lib/aws.zip', 'r'); $result = $s3client->putObject( [ 'Bucket' => 'aws-test.logicalrabbit.jp', 'Key' => 'aws.zip', 'Body' => $reader, ] ); fclose( $reader ); echo '<p>Uploaded a file. ETag = ' . $result['ETag'] . '</p>'; ?>
この後で再度オブジェクト一覧の取得を実行すれば、オブジェクトが増えているのが確認できる筈。
PHP_PEAR_PHP_BIN=/usr/local/bin/php
を設定すればOK。←結論
どっとはらい。
…いや備忘録として残しておきたかったので。なお、PHP本体のバージョンはさくらインターネットの「コントロールパネル」にて変更可能です。
% php -v PHP 7.1.4 (cli) (built: Apr 17 2017 11:51:56) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.1.4, Copyright (c) 1999-2017, by Zend Technologies
PHPはv7.1になっています。
% pecl version PEAR Version: 1.10.1 PHP Version: 5.6.30 Zend Engine Version: 2.6.0 Running on: FreeBSD www251.sakura.ne.jp 9.1-RELEASE-p22 FreeBSD 9.1-RELEASE-p22 #0: Wed Dec 3 15:24:48 JST 2014 root@www3304.sakura.ne.jp:/usr/obj/usr/src/sys/SAKURA17 amd64
しかし、peclは相変わらずPHP v5.6のまま。おかげでphp 7.xを要求するパッケージがインストールできなかったりします。
まずはphpコマンドの場所を確認。
% which php /usr/local/bin/php
実際には /usr/local/bin/php-wrapper
へのシンボリックリンクのようではありますが。
ログイン時、phpコマンドの場所を環境変数PHP_PEAR_PHP_BINにセットするようにします。その後取り敢えず現ログイン環境に反映。
% echo "setenv PHP_PEAR_PHP_BIN /usr/local/bin/php" >> .cshrc % source .cshrc
再度peclが使用するPHPのバージョンを確認。
% pecl version PEAR Version: 1.10.1 PHP Version: 7.1.4 Zend Engine Version: 3.1.0 Running on: FreeBSD www251.sakura.ne.jp 9.1-RELEASE-p22 FreeBSD 9.1-RELEASE-p22 #0: Wed Dec 3 15:24:48 JST 2014 root@www3304.sakura.ne.jp:/usr/obj/usr/src/sys/SAKURA17 amd64
これにて解決。
…したんだけど、肝心のmailparseがコンパイルエラーになって… ぐぬぬ。