MENU

プライバシーポリシー

こんにちは管理人のti_takaです。
下記、「プライバシーポリシー」に関して記載致しましたので、ご一読願います。

当サイトに掲載されている広告について

当サイトでは、第三者配信の広告サービス(Googleアドセンスもしもアフィリエイト)を利用しています。 このような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報 『Cookie』(氏名、住所、メール アドレス、電話番号は含まれません) を使用することがあります。 またGoogleアドセンスに関して、このプロセスの詳細やこのような情報が広告配信事業者に使用されないようにする方法については、こちらをクリックしてください。

当サイトが使用しているアクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。
このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。
このトラフィックデータは匿名で収集されており、個人を特定するものではありません。

この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。
この規約に関して、詳しくはこちら、またはこちらをクリックしてください。

当サイトへのコメントについて

当サイトでは、スパム・荒らしへの対応として、コメントの際に使用されたIPアドレスを記録しています。

これはブログの標準機能としてサポートされている機能で、スパム・荒らしへの対応以外にこのIPアドレスを使用することはありません。

また、メールアドレスとURLの入力に関しては、任意となっております。
全てのコメントは管理人であるti_takaが事前にその内容を確認し、承認した上での掲載となりますことをあらかじめご了承下さい。

加えて、次の各号に掲げる内容を含むコメントは管理人の裁量によって承認せず、削除する事があります。

  • 特定の自然人または法人を誹謗し、中傷するもの。
  • 極度にわいせつな内容を含むもの。
  • 禁制品の取引に関するものや、他者を害する行為の依頼など、法律によって禁止されている物品、行為の依頼や斡旋などに関するもの。
  • その他、公序良俗に反し、または管理人によって承認すべきでないと認められるもの。

免責事項

当サイトで掲載している画像の著作権・肖像権等は各権利所有者に帰属致します。
権利を侵害する目的ではございません。
記事の内容や掲載画像等に問題がございましたら、各権利所有者様本人が直接メールでご連絡下さい。
確認後、対応させて頂きます。

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。

運営者:ti_taka

[Python]Apache + Gunicorn + hug で簡単APIサーバ

先日、Apacheとmod_wsgiPythonを動かし、APIサーバを作成してみました。

kittagon.hateblo.jp

しかし、hugに備わっているBasic認証を追加することは出来ませんでした。

その後Gunicornを試してみたら、驚くほど簡単に実現できてしまいました。。

最初からこっちにすればよかった。。

前提

Pythonの環境とアプリケーションは前回のものを使います。

import sys,json,os
import hug
import util
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

HUG_USER_NAME = os.environ.get("HUG_USER_NAME")
HUG_PASSWORD = os.environ.get("HUG_PASSWORD")

authentication = hug.authentication.basic(hug.authentication.verify(HUG_USER_NAME, HUG_PASSWORD))

@hug.get("/hoge",,requires=authentication)
def hoge(text):
    hoge_list = util.getHogeList(text)
    return json.dumps({"hoge":hoge_list})

前回記述したsys.path.append('/var/www/app')はなくても今回は正常に動作しました。

また、動作させるアプリケーションは、gunicornを起動する際にパラメータとして渡すので、application = __hug_wsgi__も不要です。

Gunicornのインストール

pipでインストールします。

$ pip3.6 install gunicorn

これで完了です。

$ cd /var/www/app/
# gunicornの起動
$ gunicorn app:__hug_wsgi__
[2017-09-12 22:54:04 +0000] [3994] [INFO] Starting gunicorn 19.7.1
[2017-09-12 22:54:04 +0000] [3994] [INFO] Listening at: http://127.0.0.1:8000 (3994)
[2017-09-12 22:54:04 +0000] [3994] [INFO] Using worker: sync
[2017-09-12 22:54:04 +0000] [3997] [INFO] Booting worker with pid: 3997

アプリがポート8000で起動します。

$ curl http://localhost:8000/hoge?text=hoge

結果が帰ってくればOKです。(Basic認証をかけているので認証エラーとなりますが。)

Apacheの設定

次にApacheの設定をします。

/etc/httpd/confd/httpd.confに以下の1行を記述し、リクエストをすべてgunicornに流すよう設定します。

ProxyPass / http://localhost:8000/

gunicornを起動した状態で、ブラウザからhttp://192.168.33.10/hoge?text=hogeにアクセスして認証画面がでて認証できればOK!なのですが、なにやらまた、「Internal Server Error」が。。。

前回とまた同じです。

SELinuxの無効化

Apacheのエラーログを見ると、

[Tue Sep 12 12:03:36.233033 2017] [proxy:error] [pid 5746] (13)Permission denied: AH00957: HTTP: attempt to connect to 127.0.0.1:8000 (localhost) failed
[Tue Sep 12 12:03:36.233187 2017] [proxy:error] [pid 5746] AH00959: ap_proxy_connect_backend disabling worker for (localhost) for 60s
[Tue Sep 12 12:03:36.233202 2017] [proxy_http:error] [pid 5746] [client 192.168.33.1:62957] AH01114: HTTP: failed to make connection to backend: localhost

proxyがうまくいっていないみたいです。

エラーログを調べてみると色々情報がありました。

SELinuxが原因で、どうやらよくあることらしいです。

Linux:CentOS6でmod_proxyが動かない

こちらを参考にしました。

/var/log/audit/audit.logを見てみると、たしかに以下のエラーが。

type=AVC msg=audit(1505218092.201:865): avc:  denied  { name_connect } for  pid=5745 comm="httpd" dest=8000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:soundd_port_t:s0 tclass=tcp_socket

/etc/sysconfig/selinuxを修正して、SELINUX=disabledとします。

OSを再起動して、再度gunicornを立ち上げると、無事動作しました。

Basic認証も問題なく、きちんと認証できます。

gunicornの自動起動設定

OSを立ち上げたときにApache自動起動するよう設定しましたが、gunicornも自動起動するように設定しないとアプリをWebサーバで動作させられません。

SYSTEMCTLでDJANGOを自動起動する

ここに記載されているとおりに実行すればOKです。

$ cd /etc/systemd/system/
$ vim app.service

今回gunicornのパスは/bin/gunicornで、アプリケーションのディレクトリは/var/www/appなのでapp.serviceの中身は以下のようになりました。

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=apache
Group=apache
WorkingDirectory=/var/www/app
ExecStart=/bin/gunicorn schedule:__hug_wsgi__

[Install]
WantedBy=multi-user.target

自動起動するように設定します。

$ systemctl enable app
$ systemctl start app

OSを再起動し、ブラウザからhttp://192.168.33.10/hoge?text=hogeにアクセスして結果が出ればOKです。

まとめ

前回mod_wsgiでアプリケーションを動作させたよりももっと簡単に実現できました。

また、前回躓いたBasic認証も正常に動作させることが出来ました。

今回はgunicornを運用していこうと思います。

参考ページ

*比較 Apache+gunicornのベンチマークを取った方がいました。

さくら VPS 1G の CentOS で Apache + gunicorn のベンチマークをとってみた

[Python]CnetOS7 + Apache + mod_wsgi + hug で簡単APIサーバ作成

簡単なAPIサーバを作りたいなーと思い、やってみました。

以前はPHPを少ししか書けなかったけど、もう少し色々な言語を使いたいと思いPythonで実装してみることにしました。

色々と調べてみるとPythonにもフレームワークは色々とあるようで、DjangoとかFlaskとかありましたが、簡単に実装できそうなhugを使うことにしました。

PHPだとWebサーバ上で動かすのは簡単だったのですが、Pythonだと割と大変だったので備忘録として残しておきます。

wsgiサーバはpythonだとgunicornとかuwsgiとかがポピュラーみたいでしたが、何やら設定が難しそうな印象を受けたので、なんとなく簡単そうなmod_wsgiを使うことにしました。

最終的にやりたかったBASIC認証までを追加することは出来ませんでしたが。。。

知っている方がいたら教えてほしいです。。

※20170914 追記 gunicorn使った方が簡単でした。

kittagon.hateblo.jp

Vagrantを使ってCentOSVMを作成

Vagrantfileはこんな感じです。

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.network "private_network", ip: "192.168.33.10"
"192.168.0.100" , :bridge => "en0: Wi-Fi (AirPort)"
  config.vm.synced_folder "./", "/vagrant", type: "virtualbox", :owner => "vagrant", :groupe => "vagrant", :mount_options => ['dmode=755', 'fmode=655']
  config.vm.provision "shell", run: "always", inline: "systemctl restart network.service"
end

Vagrant+Laravelでパーミッションで詰まった」とか、「vagrant + centos7 でprivate_networkで設定したIPに接続ができない」とかで躓いた経緯があったから、

config.vm.synced_folder "./", "/vagrant", type: "virtualbox", :owner => "vagrant", :groupe => "vagrant", :mount_options => ['dmode=755', 'fmode=655']
config.vm.provision "shell", run: "always", inline: "systemctl restart network.service"

とかを記載しています。

Python3系とApacheのインストール

hugはPython3系でしか動かないので、まずはPython3系をインストールします。

Apacheyumでインストールすればいいのですが、Pythonに関してはソースからコンパイルしたりyumで入れたりとか色々やり方はあったのですが、最終的に「Python 3 を CentOS 7 に yum でインストールする手順」のやり方を参考にしたら上手くいきました。

[Python] mod_wsgiを使ってPython3.6をApacheで動かす(CentOS6系)

このあたりを参考にソースからコンパイルする方法も試してみましたが、何故かpipでmod_wsgiをインストールするところでつまずいてしまいました。Cent0S6系と7系の違い?

とりあえず下記コマンドでインストールします。

# 色々インストール
$ yum groupinstall -y "Development tools"
$ yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel
# Apacheのインストール
$ yum install -y httpd httpd-devel
# OS起動時にApacheの起動を有効化
$ systemctl enable httpd.service
# Apacheの起動
$ systemctl start httpd.service
# Pyton3.6.xのインストール
$ yum install -y https://centos7.iuscommunity.org/ius-release.rpm
$ yum install -y python36u python36u-libs python36u-devel python36u-pip

$ python3.6 -V
Python 3.6.2

無事Python3.6とApacheがインストール出来ました。

mod_wsgiのインストール

こちらもソースからインストールしたりpip経由でのインストールがあるみたいですが、あえてソースからインストールするメリットも分からなかったので、pip経由でインストールすることにしました。

先程の[Python] mod_wsgiを使ってPython3.6をApacheで動かす(CentOS6系)の後半辺りを参考にしています。

$ pip3.6 install mod_wsgi

$ python3.6 -c "import sys; print(sys.path)"
['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', '/usr/lib64/python3.6/lib-dynload', '/usr/lib64/python3.6/site-packages', '/usr/lib/python3.6/site-packages']

インストールが完了し、パケージのインストール先が/usr/lib64/python3.6/site-packagesだと分かります。

$ cd /usr/lib64/python3.6/site-packages
$ ll
total 8
drwxr-xr-x. 6 root root 4096 Sep  5 13:19 lxml
drwxr-xr-x. 2 root root  131 Sep  5 13:19 lxml-3.8.0.dist-info
drwxr-xr-x. 6 root root   84 Sep  5 09:15 mod_wsgi
drwxr-xr-x. 2 root root  141 Sep  5 09:15 mod_wsgi-4.5.18-py3.6.egg-info
drwxr-xr-x. 2 root root    6 Jul 19 04:01 __pycache__
-rw-r--r--. 1 root root  119 Jul  8 03:33 README.txt

$ cd mod_wsgi/server
$ ll
total 1048
-rw-r--r--. 1 root root   1558 Sep  5 09:15 apxs_config.py
-rw-r--r--. 1 root root   3563 Mar 31  2016 environ.py
-rw-r--r--. 1 root root 128159 Aug 29 09:28 __init__.py
drwxr-xr-x. 4 root root     60 Sep  5 09:15 management
-rwxr-xr-x. 1 root root 932872 Sep  5 09:15 mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
drwxr-xr-x. 2 root root    101 Sep  5 09:15 __pycache__

ここにある、mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.soを使います。

パスは/usr/lib64/python3.6/site-packages/mod_wsgi/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.soserverです。

Apacheの設定

これで必要なものはインストール出来たので、Apacheの設定をしていきます。

/etc/httpd/conf.d/配下にwsgi.conf設定ファイルを配置し、wsgiの設定を記述します。

LoadModule wsgi_module /usr/lib64/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so

WSGIDaemonProcess myapp user=apache group=apache
WSGIProcessGroup myapp
WSGISocketPrefix /var/run/wsgi
WSGIScriptAlias / /var/www/app/app.py

<Directory /var/www/app/>

  Options ExecCGI MultiViews Indexes
  MultiViewsMatch Handlers

  AddHandler wsgi-script .py
  AddHandler wsgi-script .wsgi

  DirectoryIndex index.html index.py app.py

  Order allow,deny
  Allow from all

</Directory>

これを記述したらApacheを再起動しておきます。

$ apachectl restart

これで、ルートディレクト/を開いたときに、/var/www/app/app.pyを動作させるという設定になりました。

hugでapp.pyの作成

とりあえずこんな感じで書きました。

import sys,json,os
import hug
import util

@hug.get("/hoge")
def hoge(text):
    hoge_list = util.getHogeList(text)
    return json.dumps({"hoge":hoge_list})

今回はGETで受け取ったパラメータを他の関数に渡して処理してもらい、その結果を返すAPIを想定しているので、この様な書き方にしています。

実際に処理する関数はutil.pyに記載しています。

以下コマンドで、開発用サーバを起動します。

$ hug -f app.py

/#######################################################################\
          `.----``..-------..``.----.
         :/:::::--:---------:--::::://.
        .+::::----##/-/oo+:-##----:::://
        `//::-------/oosoo-------::://.       ##    ##  ##    ##    #####
          .-:------./++o/o-.------::-`   ```  ##    ##  ##    ##  ##
             `----.-./+o+:..----.     `.:///. ########  ##    ## ##
   ```        `----.-::::::------  `.-:::://. ##    ##  ##    ## ##   ####
  ://::--.``` -:``...-----...` `:--::::::-.`  ##    ##  ##   ##   ##    ##
  :/:::::::::-:-     `````      .:::::-.`     ##    ##    ####     ######
   ``.--:::::::.                .:::.`
         ``..::.                .::         EMBRACE THE APIs OF THE FUTURE
             ::-                .:-
             -::`               ::-                   VERSION 2.3.1
             `::-              -::`
              -::-`           -::-
\########################################################################/

 Copyright (C) 2016 Timothy Edmund Crosley
 Under the MIT License


Serving on port 8000...

開発用のサーバがポート8000番で立ち上がるので、 $ curl http://localhost:8000/hoge?text=hoge で結果が帰ってくればOKです。 また、http://192.168.33.10:8000/hoge?text=hogeにアクセスでも見れます。

開発用サーバではなく、mod_wsgi経由でApacheでも動作しているか確認したいので、mod_wsgiでも動くようにします。 mod_wsgiで動作させるには、mod_wsgiに対応したapplicationを作る必要があります。

mod_wsgiでhugを使い、APIを作るPython hug with apache mod_wsgiを参照。

app.pyの最下部に以下の一文を追記します。

application = __hug_wsgi__

ブラウザで、http://192.168.33.10/hoge?text=hogeにアクセスして同じ結果が帰ってくればOK。

・・・なのですが、何やら「Internal Server Error」のエラーが。

Apacheのエラーログを見てみると、

[Sat Sep 09 13:28:00.511142 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] mod_wsgi (pid=7361): Target WSGI script '/var/www/app/app.py' cannot be loaded as Python module.
[Sat Sep 09 13:28:00.511233 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] mod_wsgi (pid=7361): Exception occurred processing WSGI script '/var/www/app/app.py'.
[Sat Sep 09 13:28:00.511368 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] Traceback (most recent call last):
[Sat Sep 09 13:28:00.511434 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939]   File "/var/www/app/app.py", line 4, in <module>
[Sat Sep 09 13:28:00.511441 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939]     import util
[Sat Sep 09 13:28:00.511469 2017] [wsgi:error] [pid 7361] [remote 192.168.33.1:57939] ModuleNotFoundError: No module named 'util'

なにやらutil.pyが読み込めていない模様。

Pythonで「ImportError: No module named …」が出た時の3つの対処法を参考に、sys.path.append('/path/to/dir')app.pyに追記すると直りました。

mod_wsgiでは若干挙動が違う?

Basic認証を追加

The guiding thought behind the architectureを参照すると、getの引数にhug.authentication.verify("userid","password")を与えるとBasic認証が出来るようになるみたいです。

そのままユーザーID、パスワードを記述するのも良くないので、.envファイルを作成してそこに環境変数を書くとします。

【GitHub】に載せたくない環境変数の書き方 Python こちらにdotenvの使い方が載っています。

$ pip3.6 install python-dotenv

.envの中身は↓にしました。

HUG_USER_NAME=uname
HUG_PASSWORD=pass

この中の環境変数は、以下のように取り出します。

import os
from os.path import join, dirname
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

HUG_USER_NAME = os.environ.get("HUG_USER_NAME")
HUG_PASSWORD = os.environ.get("HUG_PASSWORD")

これらの変数を用いて以下のようにBasic認証の設定を記述します。

import sys,json,os
sys.path.append('/var/www/app')
import hug
import util
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

HUG_USER_NAME = os.environ.get("HUG_USER_NAME")
HUG_PASSWORD = os.environ.get("HUG_PASSWORD")

authentication = hug.authentication.basic(hug.authentication.verify(HUG_USER_NAME, HUG_PASSWORD))

@hug.get("/hoge",,requires=authentication)
def hoge(text):
    hoge_list = util.getHogeList(text)
    return json.dumps({"hoge":hoge_list})
    
application = __hug_wsgi__

開発用サーバを立ち上げて、ブラウザからhttp://192.168.33.10:8000/hoge?text=hogeに認証画面が出て認証できればOKです。

Apacheからの接続はどうかというと、http://192.168.33.10/hoge?text=hogeに接続すると、無事認証画面が出ました!!!

が、、IDとパスワードを入れても認証出来ません。。。。

いくら調べても原因が分からない。。なんでなんだ~。。。。

今回はここで断念しました。。。

まとめ

mod_wsgiとhugを使って、簡単なAPIサーバを立ち上げることが出来ました。

ただ、最終的にやりたかったBasic認証はなぜかmod_wsgiだと正常に動作しませんでした。

hugに組み込まれている開発用のサーバとmod_wsgiとでは若干挙動が違うようです。

解決策を知っている方が居ましたら教えて下さい。

参考ページ

銭湯で痴漢された話

僕は昔からホモにモテる。何故かわからないけど。 昔は運動もしていたし、体を使うバイトもしていたので割りと筋肉質でムチムチした体をしていたからかも。

blog.livedoor.jp

ちょっと前こんな記事を見て、昔銭湯で痴漢されそうになったことを思い出しました。 しかもスーパー銭湯の系列店も同じだし。。。。

犯行現場はやはり泡風呂

先の記事でも泡風呂について言及されてましたが、自分が被害にあったのも泡風呂でした。

友人三人でスーパー銭湯に行き、泡風呂に↓のように座っていました。

┌────────────────┐
│                │
│                │
│  他 友 友 自  他    │
└────────────────┘

友人三人で並んでお湯に浸かり、自分が端でした。

ゆっくりと他愛もない会話をしながらお湯に浸かっていると、前に伸ばしている自分の膝周りちょいちょい触れるものが。。。

銭湯でたまに体が当たってしまうのはよくあることなので、その時点では何も思わず、「なんか当たんだけど〜、狭いわ〜」と友達にもぼやきながら、足を動かして跳ね除け?たりしていました。

しかし、跳ね除けても跳ね除けても何かが足に触れてきます。自分と隣の人との間には十分なスペースがあり、普通にじっとしていれば体が触れ合うような距離ではなかったのです。

しかも、触れてくる場所が少しずつ上に来て、太もも周りを触られている感触が。

気付いても何も出来ない

「隣のおっさんがこっちに手伸ばして触ろうとしてきてね?!」

そう気づいてしまったときに僕は恐怖に陥りました。

隣のおっさんは普通の何食わぬ顔で前を向きお湯に浸かっているように見えるけど、お湯の中をちらっと見ると不自然な体勢になりながらも手をこちらに伸ばしてきている!!!

恐怖を感じながらも抵抗する?ことも出来ないので、隣の友人に「サウナ行こうぜ!」と言って逃げました。

その後友人に恐怖を語ったものの、笑いものにされたのは言うまでもありません。。。

まとめ

銭湯コワイ ホモコワイ いや、痴漢コワイ

電車で痴漢されて助けを呼べない女性の気持ちが分かったなぁ〜。。

Nexus5XにAndroidOを手動インストールした手順

先日GoogleがAndroidOの開発者プレビューを公開しました。

会社での検証が必要だったので、手動インストールをしてみました。

そもそも普段からiPhoneユーザーだしAndroidを使ったことも無いので、とにかく調べながらの実践だったので、最終的に何が正解だったのかわかりませんでした。

しかし、どうにかアップデートできたので備忘録として記しておきます。

端末

  • Nexus5X(Android7.1.2)
  • MacBookAir 13-inch, Early 2015(10.11.6 OSX El Capitan)

AndroidStudio AndroidSDKのインストール

何やらAndroidを手動でインストールするためには、AndroidSDKが必要で、adb?とか言うコマンドで実施するとのこと。 AndroidStudioは必要ではないっぽいけど、後々アプリ開発もするかもしれなかったのでAndroidStudio経由でAndroidSDKをDLしました。

HomebrewにてAndroidStudioをインストール

$ brew cask install android-studio

インストールされたAndroidStudioを初回起動すると、AndroidSDKをインストールするかを聞かれるので、適当にダウンロードします。 (この辺りはどうやったか詳細を忘れました。)

するとSDKがDLされます。多分デフォルトだと大体同じかと思われます。 (自分の環境だと```$HOME/Library/Android/sdk/)にインストールされました。

このsdkフォルダ以下のplatform-toolsへのパスを通します。

$ echo "export PATH=$PATH:$HOME/Library/Android/sdk/platform-tools" >> ~/.bash_profile
$ source ~/.bash_profile

これでadbなどのコマンドが使えるようになります。

Nexus5Xを開発者モードにしUSBデバッグをオンにする

以下を参考に実施。

Android端末を「デバッグモード」(USBデバッグ)に設定する

システムイメージのダウンロード

以下より、端末に合ったファイルをダウンロードします。

Android O のダウンロード | Android Developers

Nexus5Xの場合はbullhead-opp1.170223.012-factory-338a95b1.zipというファイルで1.5Gバイトほどのサイズでした。

リカバリーモードを起動

ここからは以下を参考に実施。

Nexus端末を手動でAndroid5.0にアップデート | うめの記録帳

端末を「adb sideload」を使って手動で即座にアップデートする方法

NEXUSデバイスをSDK、adb sideloadを利用して最新ビルドのAndroidOSに手動で強制的にアップデートする方法

Nexus5Xの電源を切り、ボリュームダウンボタンを押し続けながら電源ボタン長押しで起動すると、以下のようにファストブートモードの画面になります。

f:id:ti_taka:20170417232622j:plain

ボリュームボタンのアップとダウンで選択が出来るので、リカバリーモードに合わせ、電源ボタンで選択します。すると以下のような画面になります。

f:id:ti_taka:20170417232648j:plain

電源ボタンを押しながらボリュームアップボタンを押してリカバリーメニューを表示します。

f:id:ti_taka:20170417232712j:plain

ボリュームボタン上下で、Apply update from ADBを選択すると、以下のような画面になります。

f:id:ti_taka:20170417232736j:plain

ここからがPC側の作業で、ターミナルを起動し、先程ダウンロードしてきたシステムファイルbullhead-opp1.170223.012-factory-338a95b1.zipがあるディレクトリに移動します。

ここで、以下コマンドを実行します。

$ adb sideload bullhead-opp1.170223.012-factory-338a95b1.zip

これでアップデート出来るはずだと思っていたが、以下のようなメッセージが出て終わってしまった。

loading: 'bullhead-opp1.170223.012-factory-338a95b1.zip'...
connecting...
Total xfer: 0.00x

Nexus5X側では以下のようなエラーメッセージが。。。

f:id:ti_taka:20170417232806j:plain

次に、以下のページを参考に、別のやり方を試してみた。

Android 6.0 Marshmallowを手動アップデート/インストールする方法

何やら、oem unlockというのが必要らしい。 以下を参考に実施。 Nexus5X/Nexus6Pのブートローダーアンロック方法・手順。

Nexus5Xの設定→開発者向けオプション→OEMロック解除を有効にする

再度Nexus5Xでファストブートモードを起動し、PCに接続します。 ターミナルより、以下コマンドを実行します。

$ fastboot oem unlock

すると以下のようにロックを解除しても良いか聞かれるので、ボリュームボタンでYesを選択し、電源ボタンで決定します。

f:id:ti_taka:20170417232907j:plain

その後しばらくすると再起動し、端末が初期化されます。

f:id:ti_taka:20170417233021j:plain

再度ファストブートモードを起動すると、下部のDEVICE STATEがunlockedになりました。

f:id:ti_taka:20170417233316j:plain

PC側で、bullhead-opp1.170223.012-factory-338a95b1.zipを解凍して出来たディレクトリの中に移動し、中にある./flash-all.shを実行する。

$ cd bullhead-opp1.170223.012
$ ./flash-all.sh

Nexus5X側では以下のようにdownloadingという文字が表示され、正常に進行していることが分かります。

f:id:ti_taka:20170417233550j:plain

これにて無事アップデートが完了しました。

参考

想像力がないことについて

anond.hatelabo.jp

だいぶ前の記事だがこれを読みました。あまりに自分と同じだったので「オレのことか?」と思いびっくりしました。 ただ自分は、小さい頃特にゲームばかりをやっていたわけでもなく、そこまで多い方とまでは言えないがそれなりに読書は好きだったので本も読んでいました。 なので、ゲームをやりすぎたことが想像力がない原因と結論付けることに違和感を感じました。 そこで、今回は想像力がないことの原因について考えてみました。

想像力がないことは悪いことだけではないのでは?

まず前提として、自分は想像力がないという自覚があるが、それは純粋に想像することができないという意味ではなく、想像する力を常日頃から働かせる力がない、つまり想像する習慣がないという状態だという認識です。 何が言いたいかというと、自分の場合は想像しようと思えばできると思っている、ということ。(それが本当にそうかは別として)

では、なぜできないか?

それは結局そういう習慣がないから、ということに尽きるが、習慣がないのはないなりの理由があると考えます。 理由としては、想像する必要がないような何かがあったから想像しなかった、ということが考えられます。 想像力がないということは、捉え方を変えれば既知の情報を用いて効率的に大枠を捉えているとも言えます。 想像力がないのは、ゼロから情景を構築しないで済むように、既知の景色で補完しているということなのではないでしょうか。

でもそれはつまり先入観をもって物事を捉えているだけにすぎない

既知の情報を元に目の前の事象に触れている。つまり、想像力がない=先入観、バイアスを持って物事を捉えること 複眼的思考法では、冒頭部分でこのバイアスを持って物事を捉えることの意味と、危険性について論じています。

先入観をもって物事を捉えるのは効率的で、素早い判断をするには役に立つ。 この説明には納得がいきます。 自分も想像力はないが、本を読むのは早い方でした。

しかし、やはりこれだと細い部分は抜け落ちてしまう。

入社してすぐのときに、かんたんな開発の案件に参画しました。 要件が定まらない中でも大枠を捉えてプロトタイプをどんどん作って開発を進めたことで、比較的スムーズに開発をすすめることができました。 しかし最終局面になったときに、使用するライブラリのクリティカルな仕様を読み落としていることに気づき、大変な目にあいました。 (幸い開発量としては大きい案件ではなかったので休日出勤をすることで解決できたが。。) 多分これも、自分の上記のような性質によるものだと思います。 一部の情報と自分の先入観から大枠を構築するので、確かに行動のスピードは早くはなるが、細かい部分を見落としがちになってしまう、ということなのかもしれません。

まとめ。

  • 想像力がないことは、先入観を持って物事を見ていることと一緒

  • 先入観を持つことで素早い判断ができるようになるが、それでは本質を見落としかねない

  • 自分が得た情報をしっかり検証し、そこから考えを構築することが大切

結局ぼんやりと考えていることを書いただけになってしまったので、次はこうした症状を持っている場合にどうしたら治すことができるのか、といった方法論に落とし込みたいと思います。