きっと3日坊主

Every day is day 3.

7月第3週

あるブログでその週に知ったこと / 学んだことをブログに書くということをしていていいなぁと思ったので、自分もやってみる。(いつまでつづくかわからんけど…)

IaaS と PaaS と SaaS

IaaSはOS、ハードウェア、ネットワークといった ”インフラ” の部分が用意されていて、そこに仮想サーバーを立て、ミドルウェアを自前でインストールし、アプリケーションをデプロイする。なので、Linux上での設定やセキュリティ対策もすべて自前でしなければならないが、その分自分ですべて管理し設定できるというメリットもある。

PaaSはIaaSの提供するものに加えて、データベースや言語の実行環境などのミドルウェアの範囲まで提供する。そのため、アプリケーションさえ用意すれば簡単にデプロイすることができ、OSの更新や脆弱性対策までサービスの管理下にあるので手間いらずではあるが、そのPaaSが提供するミドルウェアしか選択することができないというデメリットもある。

SaaSはアプリケーションまで用意されているので、そのサービスを使って目標を達成すればいい。GmailやこのはてなブログSaaSに該当する。

IaaS と VPS

IaaSとVPSは基本的には同じであるが、IaaSは従量課金制で柔軟にリソース(CPUやストレージなど)を変更できるが、VPSはリソースの変更のためには契約を更新しなければならないなどの違いがある

VPSレンタルサーバー(共有サーバー)

VPSレンタルサーバーって同じでしょ?って思ってたら、そういうわけではないらしい。VPSは一つの物理サーバーを複数人が使うが、ユーザーごとにゲストOSが作られゲストOSごとにリソースが確保される。そのため、他のユーザーが負荷の高い処理を行ったとしても、基本的に自分には影響しない。これがVirtual Private Server(仮想専用サーバー)という名前の由来だろう。

それに対し、共有サーバー型のレンタルサーバーは同じOS、同じリソースを複数人で使うため、他のユーザーの負荷の影響が自分にも現れる。

静的リンクライブラリと動的リンクライブラリ(.soファイル)

ライブラリには、

  • コンパイル時に結合する静的ライブラリ
  • 実行時に結合する動的リンクライブラリ

の2種類がある。

動的リンクライブラリは共有ライブラリとも呼ばれる。

実行時に結合されるので、ライブラリの改造、交換などがしやすい。

動的リンクライブラリの拡張子は、ウインドウズでは.dll、Unixでは.so(Shared Object: 共有オブジェクトの略)であることが多い。

システムコールとは

C言語の関数のことではなく、OSに処理を依頼するもので、CPU割り込みなど通常のプログラムとは違う動作をする。

そう遠くない昔の私がそうでしたが、素直なプログラマならシステムコールをCライブラリで提供されている関数のことだと定義するかもしれません。しかしこれは全く正しくありません。確かにCライブラリに含まれる関数群はシステムコールときれいに対応するものが多い一方(例:chdir)、オペレーティング>システム(OS)に対して特定の動作を要求する以上に色々な処理が行われるものもあります(例:forkや fprintf)。またこれらの他に、qsortやstrtokに代表されるような、OSの機能は特に使わずにプログラミングのための機能を提供するような関数もあります。

実は、システムコールには非常に明確な定義があります。それは、「ユーザーが実行したい操作をユーザーの代わりに実行するように、OSのカーネルに対して要求する手段」です。

チュートリアル – システムコールの書き方

intel Coreシリーズの型番の読み方

f:id:thunders1028:20170715174925p:plain

f:id:thunders1028:20170715174917p:plain

f:id:thunders1028:20170715174912p:plain

【CPU】Intel Core i7, Core i5, Core i3の世代の一覧・見分け方のまとめ

IntelのCPUの末尾についているK, S, Tなどのアルファベットについて

デカルト座標系とユークリッド空間

みんなが普通に使っている直交座標系のことを「デカルト座標系」、そして2点間の距離をピタゴラスの定理で定義したものを「ユークリッド空間」と呼ぶ。

つまり「デカルト座標系」や「ユークリッド空間」は「普通の空間」のこと。

ベクトルの基礎

構文と式と文

まず「構文(Syntax)」は、そのプログラミング言語内でプログラムが構造を持つためのルールです。多くの場合、プログラミング言語内で特別扱いされるキーワード、たとえばclassやval、ifなどが含まれ、そして正しいプログラムを構成するためのルールがあります。 classの場合であれば、classの後にはクラス名が続き、クラスの中身は{と}で括られる、などです。この節はScalaの制御構文を説明するので、処理の流れを制御するようなプログラムを作るためのルールが説明されるわけです。

次に「式(Expression)」は、プログラムを構成する部分のうち、評価することで値になるものです。たとえば1や1 + 2、"hoge"などです。これらは評価することにより、数値や文字列の値になります。

最後に「文(Statement)」ですが、式とは対照的にプログラムを構成する部分のうち、評価しても値にならないものです。たとえば変数の定義であるval i = 1は評価しても変数iが定義され、iの値が1になりますが、この定義全体としては値を持ちません。よって、これは文です。

制御構文

ペンライトとサイリウムUO

ペンライトは電池式の光る棒。電池を交換すれば再利用可能。

サイリウムは液体薬品の混合により発光する棒。使い捨て。5〜6時間光り続ける。200円くらい。

UOサイリウムの一種で同じように使い捨て。サイリウムよりも強烈に発光する。5〜6分くらいで暗くなる。つまりは短時間だけ強烈に発光するサイリウム。160円くらい。

百万畳ラビリンス

百万畳ラビリンス(上)

百万畳ラビリンス(下)

友人に勧められて読んだマンガ。SFファンタジーみたいな感じ。ゲーム会社のデバッガーとして働く主人公(ふたりいる)が異世界に迷い込んでしまうが、デバッガー業で培ったバグ探し技能や発想の機転を駆使し、異世界を攻略していく。異世界の仕様を把握し、それを逆手に取って武器にしていく様がカッコイイ。

主人公のふたりのうち一人は平凡な人間で一般的な常識人という立ち位置。もう一人は人と違う価値観や能力を持っているために人の間に入れなかった人間。この二人の対比から「人と違う人」の幸せ・価値観・向かう先みたいなものを描いていたりもする。

C言語の規格、方言の種類をざっくりまとめる

なんとなく気になったので調べてみた。主にWikipediaの情報を自分なりにまとめたもので、難しくてよくわからないのでとりあえずざっくり学ぶことが目標なので、細かい部分とかはばっさりカットしてます。

規格の種類

  • K&R
  • C89/C90
  • C99
  • C11

K&R

C言語の作者デニス・リッチーベル研究所に在籍していたカナダ出身の計算機科学者ブライアン・カーニハンの共著である「The C Programming Language」が1978年を出版され、その後標準ができるまで実質的なC言語の標準として扱われる。発展可能性のある部分は曖昧に書かれていたため、C言語の普及とともに互換性のない処理系がいくつも作られた。(これはプログラミング言語でしばしば起こる現象であり、C言語固有の現象ではない。)

C89/C90

上記のような状況から、C言語の標準規格がつくられた。まずはじめに89年にANSI(American National Standards Institute - 米国国家規格協会)で標準化され、その後90年にISOでも標準規格がつくられた。それぞれ、C89(ANSI C89)、及びISO/IEC C90という通称がある。C90の方が章立てが追加されており、その後C89もそれにならって章立てが追加された。

最大の特徴は、C++ と同様の関数プロトタイプを導入して引数の型チェックを強化したことと、void や enum などの新しい型を導入したことである。

C99

1999年に策定された、規格改定で機能拡張されたC。C++の機能をいくつか取り込んでいる。この版のCの規格を通称としてC99と呼ぶ。gccはC99にほとんど対応しているが、一部実装の部分も残っている。

主な追加機能は

  • 変数宣言がブロックの先頭でなくても良くなった。
  • ブール代数を扱うための標準ライブラリー stdbool.h が追加された。
  • 複素数を扱うための標準ライブラリーとして complex.h が追加された。
  • 64 ビット整数値を保持できる long long int 型の追加。
  • // による1行コメント。

など

C11

2011年に改定されたC言語の規格、通称C11が現在の最新のCの規格である。gccやClangが一部対応している。Unicode文字列に標準対応するなどの変更がなされた。

参考

C言語 - Wikipedia

ブライアン・カーニハン - Wikipedia

Pythonで他のディレクトリの.pyをインクルード

他のディレクトリにあるPythonスクリプトをインクルードする場合、ファイル参照パスにそのディレクトリを追加したのち、importを行う。

実行ファイルの同階層のとなりにある../mail-projectディレクトリのsend_email.pysend_mail()をインクルードする場合、次のように書く。

from sys.path import append
from os.path import dirname, abspath
append(dirname(abspath(__file__)) + '/../mail-project')

from send_email import send_mail

fromには.pyを抜いたファイル名を書くことに注意。

Python2.7からGmailを送信する

研究室で毎週特定の曜日(水曜日)の特定の時間にお知らせメールを送信する仕事を任されていて、いままでは前日の毎週火曜日にRight Inboxを使って送信設定していたが面倒になった + Right Inboxの無料枠を使い潰したくないので、Gmailを送信するPythonスクリプトを作ってそれをcronから叩くようにした。備忘録として手順を残しておきます。

Google API Client Libraryを使って、PythonからGmailを送信

今回は、Google API Client Libraryという各言語から各種APIにアクセスする用のライブラリを使った方法を書いていきます。

Gmailを送信するまでの手順

GmailPythonから送信するまでには、OAuthの認証周りを含む以下のような手順が必要です。

  1. Google Developer Consoleから新しいプロジェクトを作成し、OAuthクライアントIDを取得する
  2. authorization codeを取得する
  3. authorization codeをアクセストークンとリフレッシュトークンと交換する
  4. メールを送信する

新しいプロジェクトを作成し、OAuthクライアントIDを取得する

Google Developer Consoleから新しいプロジェクトを作ったら、API Managerの認証情報 -> 認証情報を作成 -> OAuthクライアントID を選択し、クライアントIDとクライアントシークレットを作成します。

f:id:thunders1028:20170605195438p:plain

次に出てくる「アプリケーションの種類」の部分では、今回はPythonスクリプトからAPIを叩くので「その他」を選択してください。

これで、クライアントIDとクライアントシークレットを取得することができました。

次に、Pythonからプロジェクトの情報を利用するための設定ファイル client_secrets.json を作成します。

{
  "web": {
    "client_id": "クライアントID",
    "client_secret": "クライアントシークレット",
    "redirect_uris": [],
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://accounts.google.com/o/oauth2/token"
  }
}

使い捨てみたいなスクリプトをつくるんならわざわざファイルを分けずにハードコードしてもいいんじゃない?って思うかもしれないけれど、OAuth認証をするライブラリ oauth2client がファイルから情報を読むようになっているので、ファイルに書いておいたほうが無難です。(あとでコードを公開することになったときにヘタをこくのも防止できる)

authorization codeを取得する

ここからは、Python上の作業になります(すこしブラウザ操作も入りますが…)。

authorization codeとは、アクセストークンとリフレッシュトークン(後述)を取得するために一度だけ使うトークンのようなものです。一度アクセストークンを取得するために使い終わると、そのauthorization codeはもう使うことができません。

def retrieve_authorize_code(flow):
    auth_url = flow.step1_get_authorize_url()
    webbrowser.open(auth_url) # ブラウザで認証画面を表示
    exit(0)

~~~

"""Main"""
flow = client.flow_from_clientsecrets(
    "client_secrets.json",
    scope = "https://www.googleapis.com/auth/gmail.send", # メール送信の権限を取得する
    redirect_uri = "urn:ietf:wg:oauth:2.0:oob") # authorization codeをブラウザ上に表示

retrieve_authorize_code(flow)

flowとは、OAuthの処理の流れを制御するオブジェクト…のようなものです。OAuthとflowについては、Google Client LibraryのOAuthのガイドページにあるスライドがとても簡潔にまとめられていてわかりやすいです。

さて、retrieve_authorize_code(flow) を実行すると、ブラウザが立ち上がり認証画面が表示されます。

f:id:thunders1028:20170605201537p:plain

ここで「許可」をクリックすると、画面上にauthorization codeが表示されます。

f:id:thunders1028:20170605201738p:plain

このcodeをコピーしてとっておきましょう。

実行したコードは、webbrowser.open(auth_url) のところで止まっています。Ctrl-cで一度中断してください。codeを取得してコード上に埋め込んだら(次のステップでやります)、retrieve_authorize_code(flow) はもう不要です。コメントアウトするなりしましょう。

authorization codeをアクセストークンとリフレッシュトークンと交換する

取得したauthorization codeを使って、アクセストークンとリフレッシュトークンを交換します。リフレッシュトークンとは、アクセストークンの期限が切れた際に、新しいアクセストークンを取得するのに使われるトークンです。

def retrieve_credential(flow):
    auth_code = "auth_code" 
    credential = flow.step2_exchange(auth_code)

    #with open("credential.pickle", "w") as fpickle:
    #    pickle.dump(credential, fpickle)

    #with open("credential.pickle", "r") as fpickle:
    #   credential = pickle.load(fpickle)

    return credential

auth_code のところにauthorization codeを書いてください。

flow.step2_exchange(auth_code) にauthorization codeを渡すだけでアクセストークンとリフレッシュトークンが入ったcredentialが取得できます。このcredentialはメール送信をする際に使いまわすので、DBなどに保存してください。今回は簡単にpickleで保存しました。(oauth2clientのStorage.locked_put() というのを使うのがスジらしいけどなぜか自分の環境ではうまく動かなかったのでこの方法になりました。)

メールを送信する

やっとメール送信です。

def create_service(credential):
    http_auth = credential.authorize(httplib2.Http())
    return build("gmail", "v1", http=http_auth)

def create_mail(message_text, subject, to, from_):
    message = MIMEText(message_text)
    message["subject"] = subject
    message["to"] = to
    message["from"] = from_

    return {"raw": base64.urlsafe_b64encode(message.as_string())}

def send_mail(service, raw):
    try:
        message = service.users().messages().send(userId="me", body=raw).execute()
        print "A message sent. Id: {}".format(message["id"])

    except errors.HttpError, error:
        print "An error occurred: {}".format(error)

~~~

flow = client.flow_from_clientsecrets(
    "client_secrets.json",
    scope = "https://www.googleapis.com/auth/gmail.send",
    redirect_uri = "urn:ietf:wg:oauth:2.0:oob")

credential = retrieve_credential(flow)

service = create_service(credential)

message_text = "hello, world!"
subject = "test subject"
to = "example@gmail.com"
from_ = "example@gmail.com"

mail = create_mail(message_text, subject, to, from_)

send_mail(service, mail)

疲れたので続きはあとで追記します…

Coursera MLコースを修了した

研究で機械学習を使っていることもあり、一度ちゃんと勉強したいという想いから定評のあるAndrew Ng先生のCourseraの機械学習コースを4月終わりに受講し始め、本日修了しました。

f:id:thunders1028:20170529011015p:plain

線形回帰から始まり、ロジスティック回帰、ニューラルネットワーク、応用編にはOCRアプリケーションの構築の仕方など幅広くとてもわかりやすい講義で、機械学習分野を広く一望することができたように思う。まさに自分の学びたかったことなので楽しく受講することができた。

これからは、ゼロからつくるディープラーニングというこれまた定番の本を(研究費で)Getしたので、やっていきます。

ビットコインを買ってみた

TL;DR

ビットコイン買ってみたら増えた


特に理由はないんだけど、なんか目新しいことをしたくなってビットコインを買ってみた。ブロックチェーンとか仮想通貨とかそういう周辺のことにちょっと興味があったというのもある。

使ったサイトはコインチェックというサイト。ここは決済にクレカが使えるとかいろいろ利点があった気がする(よく覚えてない)。

まったく知らなかったんだけど、暗号通貨にはビットコイン以外にも何種類もあるらしく、コインチェックではそれらも扱っているらしい。知らない世界だ。ビットコイン以外だとモナーコインくらいしか知らなかった。

いきなり増えた

数日前ここでビットコイン15000円分買ってそのまま放置してみたところ、1000円増えて16000円になった。7%くらい増えた計算。なにやらちょうど暗号通貨に関する大きいカンファレンスがあるらしく、各種仮想通貨の価格が荒れているらしい?

長期保有も手では?

暗号通貨って、ネット通販とか送金とか、これからいろんなところで使われるようになると思う。実際いろんな銀行とか小売企業がビットコインについて言及したり、実際に使えるようになったりしている。すると、信用が増して全体的に値段があがるのではないか…と思う。短期的には急騰、急落はあるだろうけど、ベースラインになる値段は右肩上がりになるはず。とすると、今のうちに買っておいて年単位で持っておけばいい感じに利益がでるのでは?

って思うけど、経済も暗号通貨もド素人の意見なのでなんともいえない。

とりあえず最初に入れた15000円分はそのまま持っといてどうなるのか観察したいと思う。上がればラッキー、下がれば勉強代ということで。

ラズパイはSELinuxが(デフォルトでは)使えない

TL;DR

ラズパイのカーネルSELinuxの設定をせずにコンパイルされている

SELinuxを使いたければ自力でコンパイルせい

環境

カーネル

$ uname -a
Linux centos-rpi3 4.4.15-v7+ #897 SMP Tue Jul 12 18:42:55 BST 2016 armv7l armv7l armv7l GNU/Linux

概要

外部公開を予定しているラズパイのSELinuxの設定をしようと何気なくgetenforceしたところ、

$ getenforce                    
Disabled

デフォルトでDisabledだと…!(ふつうCentOSではガッツリenforce)

いやな予感がする。

とりあえずpermissiveにしようと/etc/selinux/configを編集

# This file controls the state of SELinux on the system.
# 1= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=permissive #→ disabledになっていたので変更

で、再起動してみたものの…

$ getenforce                    
Disabled

なんでッ!

disabledからpermissiveに変更したときに実行されるはずのラベリングも走っている様子がない。。

/.autorelabelというファイルを作っておけば再起動時にラベリングしてくれるらしいので試してみるが…やはり応答なし。

setenforceはdisabledのときは(たしか)使えないため

$ setenforce 0
setenforce: SELinux is disabled

(^o^)…

SELinuxを触るのは初めてなのでなにか見落としが…?と思ったがとくにそういう気配もなく。

調べていると、こんな記事を発見

raspberrypi.stackexchange.com

SELinux requires kernel support, and the default Raspberry Pi kernel does not include it.

カーネルがサポートしてない(╯•﹏•╰)

SELinuxしたければ自分でカーネルコンパイルして入れなければならないとのこと。

Raspberry Pi • View topic - [Guide] SELinux {Get/Install/Setup}

ここに詳しい設定・コンパイルの仕方が書いてあるので、まぁヒマができたらやってみようかなぁ…とりあえず今はいいや(^o^