2019-05-21

Pixel 3 を急速充電できて軽いモバイルバッテリー、いいのがあったのだけど

Pixel 3 をモバイルバッテリーでも急速充電したい

Google Pixel 3 を手持ちのモバイルバッテリーで充電したら、ただの「充電中」表示。「急速充電中」になってくれません。


モバイルバッテリーのスペックを見ると「最大出力5V/1.5A」。
このバッテリーでは無理なのか(もっと大きな出力が必要なのか)、それともたとえばケーブルを変えたりすればこのバッテリーのままでも改善するのでしょうか。

モバイルバッテリーで Pixel3 の「急速充電中」表示を出すにはどうしたらいいか、調べてみました。

Pixel 3 を急速充電できる規格は?

いろいろ調べたり試したりした結論を先に書いてしまうと、Pixel3 を「急速充電中」表示にするには、どうも以下のいずれかの規格で充電する必要があるようです。

  • (最大18W) USB Power Delivery (PD)
  • (最大15W) USB Type-C Current
  • (最大10W) Google認定ワイヤレス充電器 (Qi) ※持ってないので未確認

有線の場合、充電器/バッテリー側の端子は Type-C 限定です。ポートが Type-A の場合は、どうやっても急速充電はできません。

ワイヤレスの場合、以前は普通の(5Wの)Qi充電器でもなぜか「急速充電中」の表示が出ていましたが、いつの間にか「Wirelessly Charging」に変わっていました。

日本語への翻訳がなんとも中途半端。よっぽど慌てて差し替えないといけない事情でもあったのでしょうか。
まあ確かに5Wで「急速充電中」は盛り過ぎなのですが。(後述しますが有線7.5Wで「急速充電中」にならないのですから)

有線で充電する場合、USBケーブルは両端が Type-C であれば USB 2.0 でも 3.1 でも構いません。
ただし、ケーブルの品質は充電速度に少なからず影響を与えるようです。

Pixel 3 は Quick Charge で急速充電できない

注意点として、Pixel3 は Qualcomm Quick Charge (QC) に対応していません。Qualcomm Snapdragon 搭載にもかかわらず。
(参考: Googleが「Quick Charge」などUSB PD以外の急速充電技術排除に向かう理由 (1) そもそもUSB PDとは何? | マイナビニュース
そのため急速充電対応をうたう充電器やバッテリーでも、QC規格では Pixel3 を急速充電できません。

また、Apple独自の2.1A/2.4A急速充電にも対応していません。

そういう充電器・バッテリーでは低速充電(5V/0.5Aとか)になってしまう…かというとそこまでではなく、大抵は USB Battery Charge (BC) 1.2 規格には対応していて 5V/1.5A (7.5W) での充電なら可能です。

先述の手持ちのモバイルバッテリーをテスターで計測してみました。

これもUSB BCのようです。
Pixel3 側は急速ではないただの「充電中」表示になります。

最大は USB PD 18W

Pixel3 が対応する最大入出力も確認してみました。
USB PD対応のACアダプタの実測で 9.33V/1.58A の 16W強。

適当な USB 2.0 Type-C ケーブルを使ったため、もっと高品質なら理論値の 9V/2A (18W) に近づけるのかもしれません。

USB PD対応バッテリーは重い

そんなわけで USB PD 対応のバッテリーを買おう――で話を終わってもいいのですが、ちょっと悩ましい問題があります。
現在(2019年5月)市販されているUSB PD対応のバッテリーはどれも10000mAh以上。軽くても180gくらいあります。

Anker PowerCore 10000 PD(10000mAh PD対応最小最軽量 大容量 モバイルバッテリー)【PSE認証済/Power Delivery対応/USB-C入出力ポート/PowerIQ搭載/低電流モード搭載】iPhone&Android対応

新品価格
¥4,599から
(2019/5/21時点)


↑「10000mAh PD対応最小最軽量」を標榜する人気の Anker PowerCore 10000 PD で192g。

Pixel3 の内蔵バッテリーは2915mAh。
1回フル充電できれば充分、くらいの使い方をしたい場合に10000mAhクラスはオーバースペックです。

5000mAhクラスのバッテリーなら130g程度。たかが50gほどの差ですが、普段から持ち歩くとなると地味に効いてきます。
5000mAhクラスでは Pixel3 を急速充電できないのでしょうか?

Pixel3 なら USB PD を諦めて Type-C Current もあり

そこで着目したいのが USB Type-C Current という規格。
Pixel3 は USB PD 対応といっても高々18Wです。PCみたいに60Wの出力が必要ならともかく、18W程度であれば USB Type-C Current の15W(5V/3A)でも大差ないような気がしてきます。

PD対応で5000mAhクラスのバッテリーは2019年5月時点では見つからなかったのですが、Type-C Current対応ならあるかもしれません。
宣伝文句やスペック表に「Type-C Current対応」と書かれていなくても、Type-C ポートの出力が 5V/3A であればおそらく対応しています。

逆に言うと、下記のモバイルバッテリーはType-C Current対応ではありません。
  • ポートがType-C以外(Type-Aポート+Type-C変換ケーブル/アダプタなど)
  • Type-Cポートの出力が3A未満(2.4Aなど)

5000mAhクラスでType-Cポートを持つバッテリーというのも存外見当たらなかったのですが、そんな中でやっと出くわしたのがこちら。

モバイルバッテリー Omars 5000mAh 大容量 3A出力 急速充電 USB出力 Type-C出力 薄型 軽量 USBスマホ iPhone/iPad/Android等対応 電気ベスト (5000mAh)

新品価格
¥1,199から
(2019/5/21時点)


5000mAh、重量127g! すばらしい!
さっそく注文してみました。(実はこの段階では Pixel3 側が Type-C Current に対応しているのか確証がなくギャンブルだったのですが)

結果は……?

4.9V/2.3A の11.4W

期待していた15Wには届きませんでしたが、7.5W止まりのUSB BCに比べれば5割増しです。
100円ショップ(キャンドゥ)のUSBケーブルじゃなく、高品質なケーブルにすればもっと上を目指せるかもしれません。

Pixel3 側の表示も見事「急速充電中」に。


というわけで無事、Pixel3を急速充電できるモバイルバッテリーを入手できました。
以降、このバッテリーの簡単な紹介と、このバッテリーをお薦めしがたい事情について少し。
スペックは満足なのですが……その、コンプライアンス的にちょっと。

Omars PORTABLE POWER BANK 5000mAh

箱はエヴァンゲリオン初号機っぽいカラーリング。

本体サイズは 136.6×60×10.8mm。

Pixel3(145.6×68.2×7.9mm)から縦横1cm弱ずつ小さく、重ねて持ちやすい形状です。
重さは上述したとおり127g。5000mAhクラスではもっと軽い品もありますが、Type-Cポートを持つ商品の中では最軽量の部類かと。

写真左側に見える4つの点は、充電残量確認LEDです。

ポートは3つ。

写真左から、
  • IN: Micro-B 5V/2A
  • IN/OUT: Type-C 5V/3A
  • OUT: Standard-A 5V/2.4A
合計出力15Wなので、2台同時充電は期待できなさそうです。

なお、パッケージにはなぜか Standard-A⇔Micro-B/Type-C 2-in-1ケーブルが同梱されています。せっかくバッテリー側にType-Cポートがあるのに。
このケーブルで Pixel3 を充電しても、もちろん5V/1.5A止まり。

どうせならちゃんと Type-C⇔Type-C ケーブルを同梱するか、コスト的に難しいなら潔くStandard-A⇔Micro-Bケーブルだけにすればいいのに、謎…というか商品の特長を損ねている気がします。

PSEマークがない

さて、この商品の最大の問題点。

先ほどの外箱の写真で既に予感していた方もいるかもしれませんが、PSEマークがありません
2019年2月以降、PSEマークのないモバイルバッテリーの製造・輸入・販売はアウトです。(買ったり使ったりするのは違法にはなりません)

メーカーに問い合わせたところ、以下の回答をもらいました。(要約)
  • 該当商品は2018年7月~9月頃に中国工場から日本に向けて発送した
  • 2018年10月に経産省がPSEマークについてのお知らせを出した
  • 急遽、該当商品のPSE認証を申請し取得した
  • 在庫品のごく一部がマークなしのまま残っている場合がある
  • 必要があればPSE適合証明書を提供できる

ん~…、そもそも2018年2月~2019年1月の1年間が経過措置期間だったのですから、2018年10月になって急に言われたかのようなフリをされても。
そして認証取得済みならマークなしで売っていいわけでもありません。2019年2月以降は「PSEマークがなければ流通在庫も含め販売禁止」と定められているのですから。

メーカーもメーカーですが、アマゾンジャパンも…「マーケットプレイスだから当社が販売しているわけではない」という立て付けなんでしょうが、ううーん……。

しかし他に同等商品がない

そこで他の同等商品を探してみたのですが…ない……。
もうちょっと容量が大きいType-C Current対応製品はあるのですが、だったらもうUSB PD対応の10000mAhでいいじゃん? という程度しか重さが変わらなかったり。

あと1年もすればType-Cも普及して選択肢も増えてくれるかもしれませんが、きょう(2019年5月)のところは「5000mAhで軽いがUSB BCの7.5Wで我慢」か「10000mAhで重いがUSB PDの18Wで急速充電」の2択となってしまいました。残念。

2019-05-08

Pixel 3 のLINE通知が遅い→省電力の設定変更で改善

Google Pixel 3 はLINE通知が遅い

Pixel3、LINEの通知がとにかく遅いのです。
相手から返事がなかなか来ないなあとPixel3のロックを解除してLINEアプリを立ち上げてみると、20分も前に返事が来ているじゃないですか。
そして思い出したかのように今さら届く通知!

機種固有の挙動なのか Android 9 共通の仕様なのか謎ですが、省電力設定をオフにすれば改善するそうなので、試してみました。

改善するための省電力設定は2種類

Pixel3 の省電力設定には「端末全体」と「アプリごと」の2つがあります。
自動調整バッテリー】をオフ(端末全体の設定)
どんな機能?
  • AIで学習して、使用頻度の低いアプリの電池使用を制限するとのこと
  • 全自動のみで、手動での除外設定はできません。人間が関与するのは、Googleが目指すAIの姿と相容れないということでしょうか
  • 「学習」ということはもしかすると、普段から頻繁にLINEを使っている人は制限されていないのかも
◎ 通知の速さ: 数秒~数十秒
バラツキがありますが、アプリがバックグラウンド実行中か、未起動やタスクキルされた状態か、で違うような。他にも、Wi-Fiかキャリア回線かなどで違いがありそうですが、いずれにせよ十分な速さになります。
✕ 電池の減り
体感で分かるほどバッテリーの減りが速くなります。どのくらい悪くなるかは端末の(他アプリの)利用状況にもよるので一概には言えませんが、頻繁に使うと一日もたないかも。
△ 設定切り替えの簡単さ
設定切替画面まで比較的アクセスしやすいので、頻繁にON/OFFを切り替えるのは、なくはないです。 なお、オフにしたときに、それまでの学習成果が保持されるのか失われるのか(再度オンにしたときに再利用されるのかイチから学習し直しなのか)は不明。

電池の最適化】をオフ(アプリごとの設定)


どんな機能?
  • アプリ単位の手動ホワイトリスト方式です
  • 「電話」などいくつかのシステムアプリは最初からオフに設定されており、かつオンにできないようになっています
  • LINE以外にもすばやく通知を受け取りたいアプリがあれば(Slackやメッセンジャーなど)、あわせて追加するとよいかと
○ 通知の速さ: 数秒~数分?
オンの時よりはだいぶマシになります。ただし数分かかる場合もままありました。
△ 電池の減り
オンの時よりは電池の減りは早いのでしょうが、私は体感では気づかないレベルでした。
✕ 設定切り替えの簡単さ
設定切替に手間がかかります。頻繁にON/OFFを切り替えるのは非現実的です。

最初、アプリごとに設定できる【電池の最適化】が、端末一律の設定しかできない【自動調整バッテリー】に対するホワイトリストなのかな? と思って調べ始めたのですが、どうもそれぞれ独立して作用するようです。
なので、どういう設定がよいかは人それぞれ、バッテリーのもちと通知即時性を天秤にかけてみてください。
最速の通知がほしい、バッテリーの減りは気にしない場合:
両方オフにしてしまいましょう。ただし「Pixel3はバッテリーもちが悪い」という評判を否応なく実感することになります。
普段は通知に2~3分かかるのを許容、ただしLINEやSlackでリアルタイムチャット状態のときはなる早で通知してほしい場合:
【電池の最適化】は常にオフにして、【自動調整バッテリー】を必要に応じて切り替えます。めんどくさいですが、今のところ私はコレ。
2~3分で通知が来るようになるならそれでいい、手間がかかるのはイヤという場合:
【電池の最適化】はオフ、【自動調整バッテリー】はオンのまま。これでもそう困りません。

以下、それぞれの設定手順です。

【自動調整バッテリー】オフ手順

  1. [設定]→[電池]


  2. [自動調整バッテリー]


  3. [自動調整バッテリーの使用]をオフ


【電池の最適化】オフ手順

  1. [設定]→[アプリと通知]


  2. [詳細設定]→[特別なアプリアクセス]



  3. [電池の最適化]


  4. プルダウンメニュー→[すべてのアプリ]


  5. LINEアプリ
    (下のスクショでは「最適化」になっています)


  6. [最適化しない]を選ぶ

まとめ

2種類の省電力設定のチグハグ感に釈然としないものがありますが、とりあえずマシになったので良かったです。

Google Pixel 3、Android 9 (9.0.0) での確認結果です。他の環境ではまた違う結果になる可能性があります。

2019-04-21

ドコモの Google Pixel 3 は良くも悪くもドコモらしくない

ドコモの Google Pixel 3 を買いました

ドコモの Google Pixel 3 を買いました。ヤマダ電機で驚きの機種変更0円
(とはいえヤマダのコンテンツ約6000円、ドコモの手数料2160円がかかるので実際には8千円強なのですが)

ドコモ型番(“G-01K”みたいなの)がついていないだけあって、良くも悪くもドコモ独自の機能がありません。

ドコモのスマホと違うところ

キャリア絵文字ではない
え、最初に言うとこ、そこ? と思われるかもしれませんが、この統一感のなさが解消されたのは個人的にとてもスッキリ。
↓伝統的なドコモスマホの絵文字
↓Pixel 3 はキャリア絵文字がない
ドコモメールアプリが使えない
キャリアメール(@docomo.ne.jp)はIMAPを使えるため、Gmailアプリほか任意のメールアプリで送受信できるので問題ありません。
ただ、メッセージR/Sは一切受信できません。iPhone向けにはPOP3で受け取れる環境を用意してるくせに。
「メッセージRはうざいだけ、受け取れなくてもまったく問題ない、むしろありがとう」という方も多いでしょうが、キャンペーン関係はだいたいメッセージRで来るので、受け取れないとなるとそれはそれで何かもったいない。
dアカウントの2段階認証をアプリでアンロックできない
ドコモのスマホだと、dアカウントの2段階認証をドコモアプリでさくっとアンロックできます。
しかし Pixel 3 にはドコモアプリを入れられないので、アンロック端末になれません。SMSで届く6桁のセキュリティコードを手入力するという面倒な時代に逆戻りです。
おサイフケータイでiDにdカードを登録できないらしい(現在は解消)
(2019/5追記:iDアプリのアップデートで可能になったそうです)Suica・nanacoなど他のFeliCaアプリは問題ありません。iDもdカード以外なら問題ないそうです。私はiD使っていないので実害ないのですが。

一般的な日本のAndroid端末と違うところ

SDカード非対応
その代わりGoogleフォトを容量無制限で使える等の特典はあります。でも64GBだとうかうかすると足らなくなりそう。USB OTGには対応しているようです。
地デジ非対応
フルセグのみならずワンセグも非対応。まあスマホで地デジ見たことないですが。ラジオも非搭載。

使ってみて良いところ

軽い
148gは iPhone 8 と同じ重さだそうですが(XSは177g)、Android としては軽めの部類かと。
カメラすごい
散々言われているのでここでは書きませんが、暗いところでの撮影等、さすがです。
有機EL鮮やか
最初はケバすぎ? と思ってしまいますが、数日経つと慣れます。むしろ他の液晶が白っぽく感じるように。
電池持ちは充分
巷では電池持ちが悪いと言われていますが、私はそれまで使っていたのが電池持ち激悪の LG V20 PRO (L-01J) だったので、丸一日もつだけで大満足。
ワイヤレス充電(Qi)対応
純正の充電器でないと充電時間が遅いなどと言われていますが、速く充電したければUSBケーブル使えばいいし。

使ってみて残念なところ

イヤホンジャックがない
時代の流れですが。Bluetoothイヤホンは便利なんですが、バッテリー持ちが非常に悪いのが難点。
通知ランプがない
消費電力がLED(液晶)より少なめなOELD(有機EL)のおかげで、「アンビエント表示」機能で時計や通知アイコンを常時表示できるのは確かに便利です。でもアンビエント表示は画面を覗き込まないとどんな通知が来ているか分かりません。やはりある程度離れた位置からも緑の光が明滅していればLINEが来ていると分かる通知LEDも搭載してほしかったです。
伝言メモがない
電話に出られなかったときに音声メッセージを残してほしい場合、キャリアの留守電オプションに契約する必要があります。伝言メモを重視する人は、電波が入らなかったり電源オフだったりのためにどっちみち留守電オプション付けてる気がしますが。そもそも電話(VoLTE等の電話番号での音声通話)自体をめったに使わなくなりましたが。
ストラップホールがない
今どきあるほうが珍しいとはいえ。とはいえケース付けるならケース側で対処すればいい話です。最悪ケースに自分で穴を開ければ済みます。
RAMが4GBしかない
せめて6GB、できれば8GB欲しいところ。最近のアプリはメモリを食うのか、バックグラウンドに回したアプリはけっこう頻繁にキルされている印象です。(他の4GB機種と比べても Pixel3 はタスクキルされすぎという話も。省電力か何かの機構が違う?)

まとめ

0円(実質8千円)ならお買い得でした。
性能としてはハイエンドとは言えないので、割引適用前の 98,496円 が適正かどうかは何とも。

2018-02-16

RubyのCGIをGoogle Cloud Platformの無料枠で動かしたい ~(2)SELinuxの設定

SELinuxでCGIスクリプトが500エラーになる

RubyのCGIをGCP(Google Cloud Platform)の無料枠で動かしたい~(1)セットアップ の続きです。

CGIスクリプトをブラウザから実行しようとして 500 Internal Server Error が出る場合、SELinuxの設定変更が必要かもしれません。

対策として「SELinuxをオフにすれば動きます」という大胆なブログ記事も見かけますが、できることならセキュアな状態で使いたいものです。GCPは世界中から狙われやすそうですし。
SELinuxを有効にしたままCGIを動かせるよう設定します。

問題を切り分ける(本当にSELinuxのせい?)

SELinuxを一時的に停止して、本当にSELinuxのせいなのかを切り分けます。
# setenforce 0
# getenforce ←確認
Permissive
permissiveモードは完全無効化とは違い、アクセス制御は行ないませんがログを出力します。

まずは超簡単なシェルスクリプトを /var/www/cgi-bin/test.cgi あたりに配置してみます。
#!/bin/sh
echo Content-type:text/plain
echo
echo ok!
パーミッションは755にでもして、コマンドラインで実行できることを確認します。
# cd /var/www/cgi-bin
# ./test.cgi
Content-type:text/plain

ok!
シェル上では問題なく実行できるのに http://~/cgi-bin/test.cgi にブラウザでアクセスしてエラーが出るようなら、そもそもSELinuxとは別のところに問題がありそうです。
  • Apacheの設定は正しいですか? apachectl configtest の結果は?
  • httpd.conf編集後に systemctl reload httpd しました?
  • cgiファイルのパーミッションは適切ですか?(Apacheユーザに実行権限はあります?)

シェルスクリプトで問題なかったら、次はRubyのCGIスクリプトを /cgi-bin に置きます。
#!/usr/local/bin/ruby
puts "Content-type: text/plain"
puts
puts "Ruby!"
まずはコマンドラインで実行します。ここで動かないならRubyが正しく導入できていないことになります。
次にブラウザからアクセスしてみます。エラーになるなら、スペルミスやファイルパーミッションなどを確認します。

ここまで確認して問題がなかったなら、SELinuxを元に戻してみます。
# setenforce 1
# getenforce
Enforcing
これで再びエラーが出るようになったなら、さすがにSELinuxが原因と言えそうです。

SELinuxでCGIを動かすための基本設定 (httpd_enable_cgi)

そもそもCGIが無効になっていると動きません。
# getsebool httpd_enable_cgi
httpd_enable_cgi --> off
offになっていたらonにします。
# setsebool -P httpd_enable_cgi 1

SELinuxコンテキストの設定 (httpd_sys_script_exec_t)

SELinuxでは「コンテキスト」という概念があって、適切なコンテキストが設定されていないと動作が阻止されます。
CGIの場合、ファイルが httpd_sys_script_exec_t というタイプになっている必要があります。

コンテキストは ls コマンドの -Z オプションで表示できます。
# ls -aZ /var/www/cgi-bin
drwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rwxr-xr-x. root root unconfined_u:object_r:user_home_t:s0 test.cgi
末尾が _t となっている部分がタイプです。test.cgiファイルは user_home_t タイプになっており、これではSELinuxに止められます。

chcon コマンドでタイプを変更します。
# chcon -t httpd_sys_script_exec_t test.cgi
# ls -Z test.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 test.cgi

GCEのCentOS7なら、ここまですれば全く動かないということはないと思いますが、それでも動かない場合はログを見ながら原因を探ることになります。
# audit2allow -wa
ログの読み方と対処法はここでは説明しきれないので、ハマってしまったらがんばってください……。

/var/www/html 以下でもCGIスクリプトを動かしたい (httpd_sys_script_exec_t)

CGIファイルを /var/www/cgi-bin ではない場所に置きたい場合、先ほどと同じくCGIファイルのタイプを httpd_sys_script_exec_t にすればOKです。
# cd /var/www/html
# ls -Z test.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 test.cgi
# chcon -t httpd_sys_script_exec_t test.cgi
# ls -Z test.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 test.cgi

/var/www/cgi-bin では動作するのに /var/www/html では動かない、という場合はApacheの設定を見直します。Options に ExecCGI は入ってますか?

SELinuxコンテキスト設定の永続化と適用 (restorecon)

ひととおり動作することが確認できたら、デフォルトのタイプ設定として永続化することができます。
パスは正規表現で指定します。
# semanage fcontext -a -t httpd_sys_script_exec_t '/var/www/html/.*\.cgi'
# semanage fcontext -lC
SELinux fcontext                                   type               Context
/var/www/html/.*\.cgi                              all files          system_u:object_r:httpd_sys_script_exec_t:s0
これで /var/www/html/ 以下の(サブディレクトリも含む)拡張子.cgiのファイルのデフォルトタイプが httpd_sys_script_exec_t になりました。

デフォルト設定すればいちいち chcon しなくても済むのですが、残念ながらファイルを新しく作ると自動的にデフォルトタイプになるわけではありません。
初期タイプは、ファイルの属するディレクトリから受け継ぎます。
# touch /var/www/html/test2.cgi
# ls -aZ /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 test2.cgi
ファイルのデフォルトタイプを適用するには restorecon を使います。
# restorecon -v test2.cgi
restorecon reset /var/www/html/test2.cgi context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_sys_script_exec_t:s0
# ls -Z test2.cgi
-rwxr-xr-x. root root unconfined_u:object_r:httpd_sys_script_exec_t:s0 test2.cgi

結局ファイルを作るたびにタイプ変更のコマンドを叩く必要があるなら、デフォルト設定って何の役に立つの? という気持ちになるかもしれませんが、restorecon は chcon と違ってタイプを具体的に指定しなくて済むのはメリットです。

CGIスクリプトからファイルに書き込みたい (httpd_sys_rw_content_t)

CGIの実行は可能になったものの、CGIスクリプトからファイルに書き込もうとするとSELinuxによって阻止されます。
たとえ書き込み先のファイル権限が 666 であってもです。

書き込み先のファイルにはSELinuxのタイプ httpd_sys_rw_content_t が必要です。
ファイルをCGIスクリプトから作成したい場合は、書き込み先のディレクトリにも同タイプを設定します。

chcon で毎回設定してもいいですが、たとえば data という名前のディレクトリは一律でデータ用とするなら、デフォルト設定にしてもよいでしょう。
# semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/html(/.*)?/data(/.*)?'
これで /var/www/html 以下の data ディレクトリと、dataディレクトリ内のすべてのファイルやディレクトリのデフォルトタイプが httpd_sys_rw_content_t になります。

data ディレクトリを httpd_sys_rw_content_t タイプにしておくと、CGIスクリプトでデータファイルを新規に作成した場合、ファイルのタイプは自動的に httpd_sys_rw_content_t になります。新しく作ったファイルはディレクトリのタイプを受け継ぐためです。

CGIスクリプトから通信したい (httpd_can_network_connect)

CGIスクリプトからローカルファイルの読み書きは可能になりましたが、スクリプト内で通信をしようとするとSELinuxに阻止されます。
curlを呼んだりしたい場合は、通信の許可設定が必要です。
# setsebool -P httpd_can_network_connect 1

httpd関連だけSELinuxを止めたい(permissive_httpd_t)

とりあえず以上の設定でCGIスクリプトはひととおり動くはずですが、どうしてもエラーが解消しきれなくて時間がない場合、SELinuxを丸ごと permissive モードにするのではなく、httpd 関連のみ permissive にする方法もあります。
# semanage permissive -a httpd_t
# semodule -l | grep permissive
permissive_httpd_t      (null)
permissivedomains       (null)

問題が解決したら元に戻します。
# semanage permissive -d httpd_t

2018-02-02

RubyのCGIをGoogle Cloud Platformの無料枠で動かしたい ~(1)セットアップ

RubyのCGIをGCPで(無料で)動かしたい

自分で使う用のこまごまとしたWebアプリを動かすために手頃なレンタルサーバーを借りていたのですが、年契約の更新時期が来ました。
ふと思い出したのが昨春Google Cloud Platform(GCP)の無料枠拡大の話。2年目以降も無料で使えるのはかなり限られた構成になりますが、自分しか使わないサーバーなのでスペックは足りそう。乗り換えてみることにしました。

GCP(の無料枠)でPHPやRuby on Railsを動かすための情報はいくつか見つかったのですが、CGIの話は見当たらなかったので、作業記録やひっかかりポイントを書き残しておきます。

無料トライアルに申し込む

無料枠内しか使わないつもりでも、クレジットカードの登録は必要です。

申込みから初期セットアップまでの手順はいろんな方がまとめてくれているので、ここでは改めて書きません。たとえば下記などを参考に。

OSはCentOS 7にしました。個人的にはDebianのほうが慣れていますが仕事だとCentOSが多いので、これを機に馴染んでおこうかと。

他、ポイントとしては:
  • ゾーンはus-westを選びます。usしか無料にならないので、せめて日本から一番近い西海岸を
  • ディスクサイズはせっかくなので無料枠の上限である30GBに上げます
  • 固定(静的な外部)IPアドレスを割り当てます(1つなら無料)

最低限の初期設定

GCE(Google Compute Engine)のVMインスタンスが起ち上がったら、Web上の管理画面からブラウザ上で動くSSHクライアントを起動できます。
最終的には手元のPC等のネイティブSSHクライアントから入ったほうが快適なのですが、とりあえずの作業はブラウザからでも事足ります。ちょっとレスポンスが遅いのが難点ですが。

ブラウザSSHだとbash上でCtrl+Wを叩くと、1語消えるかわりにブラウザが「このサイトを離れてもよろしいですか?」と訊いてくる問題もありますが、ChromeならSSH for Google Cloud Platform 拡張機能をインストールすればCtrl+WもCtrl+NもCtrl+Tも叩き放題です。

最低限、次のあたりを設定しておきます。
  • 22番ポートをファイアウォールで遮断。セキュリティ対策
  • 代わりに適当なポートでSSHで入れるように
  • タイムゾーンを日本に
    $ sudo timedatectl set-timezone Asia/Tokyo

ほかはお好みで。

Apacheをインストール

$ sudo yum install httpd
/etc/httpd/conf/httpd.conf などを適宜編集したら、
$ sudo systemctl enable httpd

DNSやSSLの設定は後回しにして、いったん手元のPC等から http://IPアドレス/ でwelcomeページを表示できることを確認します。
表示できない場合は、Apacheやファイアウォールなどの設定を見直します。

ところで CentOS 7 ではサービスの制御は systemctl を使いますが、httpd.conf を編集した後に反映させるのは graceful ではなく reload です。
$ sudo systemctl graceful httpd
Unknown operation 'graceful'.
$ sudo systemctl reload httpd
$ (反映された)

/usr/lib/systemd/system/httpd.service には次のように定義されており、ちゃんと graceful してくれます。
(略)
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
(略)



yumのRubyは古い

Rubyもyumで…と思いきや、バージョンがずいぶん古いのでした。
$ yum info ruby
(略)
Available Packages
Name        : ruby
Arch        : x86_64
Version     : 2.0.0.648
Release     : 30.el7
(略)
仕方ないのでrbenvを入れて自分でビルドします。
ちょっと重い作業になりますが、レンタルサーバーと違って新しいバージョンが使えるというのはうれしいものです。いまだに1.8しか使えないレンタルサーバーとかありますし……。

Rubyビルドの事前準備(パッケージ導入・スワップファイル作成)

ビルドに必要なパッケージを入れます。
$ sudo yum -y install git gcc openssl-devel readline-devel
(他にも何か入れたかも。ビルド中にエラーが出たら適宜yum installしてください)

最初、このままビルドに進んだら途中でメモリ不足になってしまいました。
無料枠のf1-microインスタンスのメモリは0.6GB。国民機PC-9801の1000倍ですが、それでも足りないようです。

スワップファイルを作ります。
$ sudo su -
# dd if=/dev/zero of=/swapfile bs=1M count=1024
# chmod 600 /swapfile
# mkswap /swapfile
# swapon /swapfile
# free -m
           total       used       free     shared buff/cache  available
Mem:         588        148        319          4        119        323
Swap:       1023          0       1023

1GBにしたのにはキリがいいからですが、推奨値はRAMの2倍なので1.2GBのがよかったのかもしれません。ただ、1GBでもRuby 2.5.0のビルドには問題ありませんでした。

今後もスワップファイルを常用したければ /etc/fstab に書きます。
/swapfile       swap    swap    defaults        0 0

rbenvをシステム全体で使えるようにインストール

rbenvの基本的な導入方法は https://github.com/rbenv/rbenv に書かれているとおりですが、~/.rbenv/ にインストールしてしまうとCGIで使うにはちょっと不便です。システム全体で使えるよう /opt/rbenv に導入することにします。

rbenvを /usr/local 以下に導入した話をよく見かけますが、FHS(Filesystem Hierarchy Standard)では /usr/local には任意のディレクトリを作ってはならないと規定されています。パッケージ名でディレクトリを作りたければ /opt を使うそうです。

.bash_profile に書く設定は代わりに /etc/profile.d/ 以下に置けば、自動的に全員にロードされます。
# git clone https://github.com/rbenv/rbenv.git /opt/rbenv
# echo 'export RBENV_ROOT="/opt/rbenv"' >> /etc/profile.d/rbenv.sh
# echo 'export PATH="${RBENV_ROOT}/bin:${PATH}"' >> /etc/profile.d/rbenv.sh
# echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh
# . /etc/profile.d/rbenv.sh

Rubyをビルド・symlink作成

Rubyのバージョンは事情に応じて選びます。
特に事情もないなら最新版(現時点では2.5.0)でよいかと。
# mkdir -p "$(rbenv root)"/plugins
# git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
# rbenv install 2.5.0
(20分くらいかかりました)
# rbenv global 2.5.0
# ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]

このままでもRubyは実行できますが、CGIスクリプトのファイル1行目を次のように書くことになります。
#!/opt/rbenv/shims/ruby
ちょっと見慣れなすぎて覚えられなさそうなので、見知ったパスにシンボリックリンクをはってしまいます。
# ln -s /opt/rbenv/shims/ruby /usr/local/bin/ruby

SELinuxの設定変更

この状態でももうCGIスクリプトは動作するのですが、cgi-bin ディレクトリ以外に置くと 500 Internal Server Error になってしまいます。
/var/www/html 以下でもCGIスクリプトは動かしたい場合、SELinuxの設定変更が必要です。

長くなってきたので次回の記事で。