ubuntuで再起動が必要な理由を調査

サーバーのメンテでカーネルを更新したのですが、再起動後も「再起動が必要です」という表示が出ていました。

実行中のカーネルのバージョンも最新だったので、なぜ再起動が必要かを調査してみました。

まず、再起動が必要な場合 /var/run/reboot-required 内にその旨が記述されています。

$ cat /var/run/reboot-required
*** システムの再起動が必要です ***

また、 /var/run/reboot-required.pkgs を参照すると再起動が必要なパッケージの理由を閲覧できます。

$ cat /var/run/reboot-required.pkgs
linux-base

linux-baseというとカーネル関連のアップデートですが、その詳細がよく分かりませんね・・・

どうやら /usr/share/update-notifier/notify-reboot-required というスクリプトが実行されることでこの文章が記録されるらしいです。

スクリプト中に次の記述があります。

if [ "$0" = "/etc/kernel/postinst.d/update-notifier" ]; then
    DPKG_MAINTSCRIPT_PACKAGE=linux-base
fi

驚いたことにlinux-baseという文章は決め打ちで記述されているようです(だったらreboot-required.pkgsは必要ないのでは・・・)。

また、update-notifierはOSのアップデートやクラッシュレポートなどを監視・報告するプログラムのようです。

具体的に再起動で適用されるパッケージを表示したかったのですが、少し調べた限りでは方法が分かりませんでした。

とりあえず再起動を行って様子を見ようと思います。

Ubuntu 16.04のDocker更新時にCould not resolve hostエラー

Ubuntu ServerのDocker更新時に以下のエラーが出たので対応。

$ sudo apt update
エラー:1 https://download.docker.com/linux/ubuntu xenial InRelease
  Could not resolve host: download.docker.com

調べるとIPv6で通信時にエラーが出ているようです。

本来ならIPv6で更新できるのが理想と思いますが、IPv4で更新するように設定することで暫定的に対処しました。

参考サイト

$ echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4

私の環境ではこれでアップデートできるようになりました。

考えてみるとIPv6の設定がいろいろと疎かになっている気がするので、ちゃんと設定していればエラーが起きずに更新できるのかな・・・頭の痛い問題です・・・

【Python】seleniumのcookieをrequestsで使う

seleniumは重いのでログイン処理など動的な値の生成が必要な時だけ使いたい。

ログインした後はrequestsとかでサクッと処理したい、そんな時にはcookieの受け渡しが必要になります。

受け渡すのは意外と簡単で、例えばニコニコ動画にseleniumでログインしてrequestsでマイリストを取得したい時は、

# -*- coding:utf-8 -*-

import os
import requests
from selenium import webdriver


def get_mylist(login_id, password):
    # ログインを行う
    login_page_url = "https://account.nicovideo.jp/login"
    if os.name == "nt":
        phantomjs_path = "node_modules/phantomjs/lib/phantom/bin/phantomjs.exe"
    else:
        phantomjs_path = "node_modules/phantomjs/bin/phantomjs"
    try:
        driver = webdriver.PhantomJS(phantomjs_path)
    except FileNotFoundError:
        print("PhantomJSの実行バイナリが見つかりませんでした。\n"
              "npm install phantomjs \n"
              "を実行してインストールしてください。")
        return
    driver.get(login_page_url)
    login_id_form = driver.find_element_by_id("input__mailtel")
    password_form = driver.find_element_by_id("input__password")
    submit_button = driver.find_element_by_id("login__submit")
    login_id_form.send_keys(login_id)
    password_form.send_keys(password)
    submit_button.submit()
    # cookieの受け渡し
    session = requests.session()
    for cookie in driver.get_cookies():
        session.cookies.set(cookie["name"], cookie["value"])
    # requestsで取得
    mylist_url = "http://www.nicovideo.jp/api/deflist/list"
    response = session.get(mylist_url)
    print(response.text)


if __name__ == "__main__":
    get_mylist("your_id", "your_password")

のように実現できます。

なお、コードはほとんど前回の記事の流用なので、PhantomJSなどのセットアップなどについてはそちらを参照してください。

また、クッキーを受け渡す処理は

    session = requests.session()
    for cookie in driver.get_cookies():
        session.cookies.set(cookie['name'], cookie['value'])

のみで、PhantomJSからdict型のcookieを取得し、requestsのcookiejarにセットしているだけです。

ニコニコ動画にpython+selenium+PhantomJSでログイン

以前作成したニコニコ用のpythonスクリプトが動かなくなっていたので原因を調査。

どうやらログインの形式が変わったようで、古い方のログインページが削除されてしまったようです。

また、新しいログインページはJavascriptで動的にログイン情報を生成するため、今まで使っていたrequestsではうまくいきませんでした。

そこで、Javascriptなどの動的な要素を再現できるselenium+PhantomJSを用いてニコニコ動画にログインしてみたいと思います。

準備

pipでseleniumをインストールして、npmでPhantomJSを入れます。

npmは実行したいスクリプト直下のディレクトリ内で実行してください。

pip install selenium
npm install phantomjs

この作業により、node_modulesディレクトリ内にphantomjsが入ります。

スクリプト

# -*- coding:utf-8 -*-

import os
from selenium import webdriver


def login(login_id, password):
    login_page_url = "https://account.nicovideo.jp/login"
    if os.name == "nt":
        phantomjs_path = "node_modules/phantomjs/lib/phantom/bin/phantomjs.exe"
    else:
        phantomjs_path = "node_modules/phantomjs/bin/phantomjs"
    try:
        driver = webdriver.PhantomJS(phantomjs_path)
    except FileNotFoundError:
        print("PhantomJSの実行バイナリが見つかりませんでした。\n"
              "npm install phantomjs \n"
              "を実行してインストールしてください。")
        return
    driver.get(login_page_url)
    login_id_form = driver.find_element_by_id("input__mailtel")
    password_form = driver.find_element_by_id("input__password")
    submit_button = driver.find_element_by_id("login__submit")
    login_id_form.send_keys(login_id)
    password_form.send_keys(password)
    submit_button.submit()
    mylist_url = "http://www.nicovideo.jp/api/deflist/list"
    driver.get(mylist_url)
    print(driver.page_source)


if __name__ == "__main__":
    login("your_id", "your_password")

ブラウザの機能をそのまま実行してくれるので、ソースからhidden属性を探したりする必要も無くとっても簡単ですね。

ただ、少し重いようなので大量の処理には不向きかもしれません。

requestsのようなモジュールとうまく使い分けができると便利です。

WindowsでPyCharmの高DPIスケーリング問題に対処する

TL;DR

IDEのHelp > Find Action > Switch IDE Boot JDK にてIDE起動に用いるJDKをJetBrainsが提供する[bundled]の物からOracleが提供する物に変更する。

本文

普段からPyCharmにお世話になっているのですが、少し前からPyCharmを起動するたびにこの警告が出ていました。

PyCharm(というかJavaの問題らしいですが)でWindowsのUIスケール(設定>システム>ディスプレイ>拡大縮小とレイアウト から設定できます)に対応できていないらしく、画面の実際の大きさに対応して適切なフォントサイズで描画できないようです。

もともとの原因はJava8でのUIスケールのサポートが限定的らしく、最新のJava9にしないと完全サポートされない事らしいですが、残念ながらPyCharmはJava9では動かないようです(公式サイトより)。

実際、現在ラップトップディスプレイで作業を行っていますが、家の32インチディスプレイの設定が引き継がれており文字がとても小さいです・・・

これに対処するために、公式サイトではいくつかの設定案を提案しています。

  1. フォントサイズを変更してみる
  2. 互換性設定からウィンドウ全体を拡大するよう変更する

1はディスプレイを変更した際にいちいちフォントを設定しなおすのが面倒で、2は単なる画像拡大なので文字がぼやけて大変見づらいです。

そこで、JetBrainsが自社のIDE用にOpenJDKベースのカスタム版JDKを提供しているような話を思い出したので、そちらに変更することで問題が修正されていないか期待しました。

IDEを起動する際のJDKの変更は、Help > Find Action > Switch IDE Boot JDK から行えます。

ここでは、[bundled]と書かれているものがバンドルされているもので、もう片方がOracle公式の物のようです。

なんと、設定を見てみると既にJetBrainsのカスタム版JDKで起動するように設定されていました・・・

ならば物は試しということでOracle版のJDKを選択して再起動すると、驚いたことに警告が出ません。

設定からスケーリングを変更してみましたが、設定に合わせてフォントサイズが見事にスケールしてくれます。

スケーリング問題は公式JDKには発生しておらず、OpenJDKのみの問題だったということでしょうか・・・

よくわかりませんが、無事に解決できてよかったです。

フォントはかなり昔に作ったRicty for Powerlineを使っているのですが、そろそろ変えたいですね・・・

「ご注文はうさぎですか?? ~Dear My Sister~」を観てきた

日記です。

11月11日に公開された「ご注文はうさぎですか?? ~Dear My Sister~」を観てきました。

12日と合わせて2回行ったので、その感想を書きたいと思います。

いろいろ書く予定ですが、言いたいことはただ一つ。完全完璧に最高でした。

ネタバレは少しあるのでご注意。しかし基本的に最高と叫んでるだけです。

良かった点

  • ストーリーが最高
  • 作画がすごく良い
  • 監督と福監督が最強で最強
  • ココアちゃんがかわいい
  • もちろん全員かわいい

ストーリーが最高

私は原作は2巻までしか読んでいないのですが、5巻に収録されている3話分を元に制作しているみたいです。

ラビットハウスとココアちゃんの帰省先で繰り広げられるそれぞれの話が良い。

テンポも良くかわいい・ほっこりの波動が次々と押し寄せてくる。でもちゃんと面白い。

ココアちゃんの帰省先が素敵すぎる。

お祭りと花火が最高。好きって感じです。

作画がすごく良い

作画がめっちゃくちゃ良いです。

EDクレジットの人数がかなり多かった気がします。

制作はアニメ1期2期を手掛けたWhite Foxではない?

かわいいキャラがかわいく動いて最強に見えます。

キャラデザが神。特に7人の私服および浴衣とモカ姉・ココアのお母さんのラビットハウス服とココアちゃんの私服がすごく良い(重複)。

髪の動きとかもしっかり付いててかわいかったです。

監督と副監督が最強

監督はアニメ1期2期の橋本監督です。本当に信頼できる。

かわいくて素敵な女の子たちの演出について、彼の右に出るものはいません。

そして副監督がなんとアニメゆゆ式の監督であるかおりさんです。

初見でクレジットに載っているの見て驚きましたが、2回目に意識しながら見るとかおり節が全開でしたね。。

ツッコミの間の取り方や中盤のチマメ隊とリゼちゃんのやりとりはゆゆ式でも見たような雰囲気がありました。

橋本監督の素敵な演出とかおり副監督のノリと面白さが合わさる・・・

これはもう日常系の最強完全体といっても過言ではありません。

ココアちゃんがかわいい

今作の主人公は特に決まっていないのですが、やっぱり全体の流れはココアちゃん手動で話が進みます。

ココアちゃんの喜怒哀楽の表情変化はどれも素晴らしいです。

感情を全身で表現する姿は本当にかわいいく最高に癒されます。

この世の物とは思えません。(この世の物ではない)

作画も良く、感情も良く、服装も動きも良い。

こんなにかわいい女の子は他にいません。(異論は認めます)

もちろん全員かわいい

さっきも書きましたが、本作に明確な主人公は存在しません。

わずかにココアちゃんの出番が多かった気はしますが、全員がしっかりと話に絡んで良い味を出しています。

さらにリゼのお父さんやモカ姉・ココアのお母さんなど、今まであまり出ていなかったキャラが観れたのも良かったです。

それぞれの登場人物にそれぞれの”ここすき”。是非探してみてください。

まとめ

観て。

Azureのgit cloneで500が出た際の対処

Azureのプロジェクトをgit経由でクローンしようとしたのですが、非常に長い時間がかかる上にレスポンスが500でした。

$ git clone https://user@subdomain.scm.azurewebsites.net:port/project.git
fatal: unable to access 'https://user@subdomain.scm.azurewebsites.net:port/project.git/': The requested URL returned error: 500

この時、URLを以下のように変更すると何故かうまくいきます。

https://user@subdomain.scm.azurewebsites.net:port/project.git

から

https://subdomain.scm.azurewebsites.net:port/project.git

と変更します(ユーザー名を除去しただけですが)。

ユーザー名とパスワードはクローン時に入力するなど、URLに含めない形です。

Azureのバグなのかわかりませんが、早く治るといいですね・・・

Nexus 5Xの起動ループを修理

※データ消失の可能性がありますので、自己責任でお願いいたします

Nexus 5Xが起動画面から再起動のループに陥り、正常に起動しなくなりました。

調べたところこの現象は一定数のNexus 5Xに発生するらしく、BLOD(Boot loop of death)と呼ばれています。

また、この現象はNexus 5Xのブートローダーを有志が作成したものに書き換える事で解決できるようです。

今回は復旧が成功しましたので、ノウハウをメモしておきます。

方針

このページを参考に、Nexus 5Xにカスタムブートローダーを入れます。

Nexus 5XにインストールされているAndroidバージョンによって必要なファイルが異なりますので、注意が必要です。

作業をする前に

今回作業を行う対象はブートローダー領域・リカバリー領域・システム領域の3つです。

Googleが配布しているファクトリーイメージにはこれら3つが含まれています。

また、Nexusシリーズは毎月アップデートが行われており、ファクトリーイメージもそれに合わせて毎月更新されています。

それぞれ必要なブートローダーが異なりますので、対応する月のブートローダーが必要となります。

クリーンインストール

この操作によりユーザー領域のデータなどすべて消えますのでご注意ください。

Nexus 5Xをすべてリセットして再インストールする場合は、公式の配布ページから対応するファクトリーイメージをダウンロードします。

解凍後、flash-all.batを実行して、Nexus 5Xにイメージをインストールします。

最後にこのサイトで公式ファームウェアに対応するブートローダーをインストールして完了です。

ブートローダーだけ入れ替え

このPOSTの”Process for System image”の項を参考にしてください。

OTAでアップデートしたらBLODが再発した

このPOSTの”Process for OTA”に従って手動でアップデートを適用してください。

ただし、この場合は既にリカバリーイメージがロードされていますので、手順6のadb sideload update-oprXXXXXX.zipのコマンドは必要ありません(勝手にアップデートが始まります)。

また、BLODが再発した場合、その時点でOTA経由でダウンロードしたアップデートはインストールできていませんので、そのアップデートより1つ前のバージョンのブートローダーとリカバリーが必要な点に注意してください。

例えば11月のアップデートをOTA経由で適用してBLODに陥った場合、まずは10月版のブートローダーおよびリカバリーを入れる必要があります。

これについてはリンク先にも書いてありますので、手順通りに進めれば問題ありません。

fastbootをインストール

初めにAndroid SDKをインストールします。

Android Studioを丸ごと入れるとすごく重いので、SDKツールのみダウンロードしてください。

開くとtoolsというディレクトリが入っていますので、適当な場所に解凍してください。

Windowsの場合はtools/bin/sdkmanager.exeをコマンドラインから実行します。

.\sdkmanager.exe platform-tools

これでtoolsと同じディレクトリにplatform-toolsディレクトリが作成され、adbやfastbootが入ります。

うまくいかない時は

platform-toolsを入れなおしてみる

既にfastbootコマンドが入っており、それを使って失敗してしまう場合はplatform-toolsを入れなおしてみると良いと思います。

platform-toolsは頻繁に更新が行われており、古いものはすぐに使えなくなります。

いっそのことクリーンインストールを試してみる

データは消えますが、一番成功する確率が高い気がします。

ファクトリーイメージ内のスクリプト(flash-all.bat)はリカバリーと同時にいろいろとクリーニングをしてくれているみたいなので、工場出荷時に戻すことで諸問題を解決できる可能性があります。

リンク

Djangoのテンプレートでbodyに変な文字列が入る際の対処法

AzureのDjangoの最初から入っていたテンプレート(layout.html)を使用する際、bodyタグのすぐ下によくわからない文字が入ってコンテンツの位置がずれていたので対策。

以下サイトに原因と解決策が書いてありました。

https://stackoverflow.com/questions/21204834/django-template-extends-tag-added-extra-space-on-top

ちゃんと読んでいませんが、layout.htmlファイルのエンコーディングがBOM付きUTF-8になっていたことが原因の模様。

これをBOMなしUTF-8で保存してあげると問題は改善しました。

しかし、ファイルのエンコーディングが違ってもちゃんと出力してくれるのは素晴らしいですね(そのせいで今回の問題が発生したとも言えるのですが・・・

備忘録や作ったアプリなどを置いています。