2017年7月11日火曜日

pdftk で pdf ファイルを結合

pdftk で pdf ファイルを結合してみました。

$ pdftk original1.pdf original2.pdf original3.pdf cat output new.pdf

以下のサイトには回転や分割の方法なども載っています。


2017年1月29日日曜日

Google App Engine で cron

app.yaml と同じ場所に cron.yaml を設置

$ cat cron.yaml
cron:
- description: kick continuously
  url: /
  schedule: every 5 minutes

cron.yaml の書き方はこのあたりを参照

デプロイ

$ gcloud app deploy app.yaml cron.yaml --project PROJECT_ID
  • cron.yaml も指定する必要がありました。

2017年1月28日土曜日

Google App Engine で ソースコードを編集

Google App Engine で Python サンプルアプリをデプロイ でデプロイしたサンプルアプリを編集してみます。

今まで、[Hello World!] と表示されていたものを [Hello Python!] と表示されるように編集します。


環境

  • Ubuntu 16.04.1 LTS

Google Cloud SDK をインストール

パッケージをインストール

$ sudo apt install wget
$ sudo apt install git

Create an environment variable for the correct distribution

$ export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"

$ echo ${CLOUD_SDK_REPO}
cloud-sdk-xenial

Add the Cloud SDK distribution URI as a package source

$ echo "deb https://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
deb https://packages.cloud.google.com/apt cloud-sdk-xenial main

$ ls -la /etc/apt/sources.list.d/
total 12
drwxr-xr-x 2 root root 4096 Jan 28 17:18 .
drwxr-xr-x 6 root root 4096 Jan  2 15:25 ..
-rw-r--r-- 1 root root   64 Jan 28 17:18 google-cloud-sdk.list

$ cat /etc/apt/sources.list.d/google-cloud-sdk.list
deb https://packages.cloud.google.com/apt cloud-sdk-xenial main

Import the Google Cloud Platform public key

$ wget https://packages.cloud.google.com/apt/doc/apt-key.gpg -O - | sudo apt-key add -
  • 参考にしたページでは crul を使って apt-key.gpg をダウンロードしていましたが、なぜかうまくいかなかったので wget を使いました。

Update the package list and install the Cloud SDK

$ sudo apt-get update && sudo apt-get install google-cloud-sdk

$ which gcloud
/usr/bin/gcloud

認証

以下実行

$ gcloud init

[You must log in to continue. Would you like to log in (Y/n)?] で [Y] を入力

[ Go to the following link in your browser: ] と表示され、https://accounts.google.com/o/oauth2/auth?redirect_uri=... で始まる URL が表示されたのでブラウザで開く

Google アカウントを選択

[Google Cloud SDK が次の許可をリクエストしています] と表示されたので内容を確認して [許可] をクリック

[このコードをコピーし、アプリケーションに切り替えて貼り付けてください] に続き、コードが表示された

コマンドの画面に戻り、[Enter verification code] にブラウザで表示されたコードを張り付け

[Pick cloud project to use] が表示されたので [mytest-20161229] を選択


App Engine アプリのソースコードを編集

リポジトリを確認

Google Developers Console にアクセス

プロジェクトを選択

左上のメニューアイコンをクリックし [開発] を選択

左側のメニューで「レポジトリ」をクリック

以前にデプロイしたサンプルアプリのリポジトリ名 [python-gae-quickstart] を確認できたのでこのリポジトリのソースコードを編集します。

Cloud Repository をローカルにクローン

$ gcloud source repos clone python-gae-quickstart --project=mytest-20161229

ローカルの Git リポジトリに移動

$ cd python-gae-quickstart/

ディレクトリの内容を確認

$ ls -la
total 60
drwxrwxr-x 4 ubuntu ubuntu  4096 Jan 28 21:08 .
drwxrwxr-x 3 ubuntu ubuntu  4096 Jan 28 21:08 ..
-rw-rw-r-- 1 ubuntu ubuntu   247 Jan 28 21:08 appengine_config.py
-rw-rw-r-- 1 ubuntu ubuntu   170 Jan 28 21:08 app.yaml
-rw-rw-r-- 1 ubuntu ubuntu  3045 Jan 28 21:08 CONTRIB.md
drwxrwxr-x 8 ubuntu ubuntu  4096 Jan 28 21:08 .git
drwxrwxr-x 4 ubuntu ubuntu  4096 Jan 28 21:08 lib
-rw-rw-r-- 1 ubuntu ubuntu 11357 Jan 28 21:08 LICENSE
-rw-rw-r-- 1 ubuntu ubuntu   424 Jan 28 21:08 main.py
-rw-rw-r-- 1 ubuntu ubuntu   342 Jan 28 21:08 .playground
-rw-rw-r-- 1 ubuntu ubuntu  2761 Jan 28 21:08 README.md
-rw-rw-r-- 1 ubuntu ubuntu   275 Jan 28 21:08 requirements.txt
-rw-rw-r-- 1 ubuntu ubuntu  2812 Jan 28 21:08 vendor.py

Git のメールアドレスとユーザー名を設定

$ git config --global user.email "Gmail のメールアドレス"

$ git config --global user.name "名前"

試しに main.py を編集

編集した箇所を確認

$ git diff
diff --git a/main.py b/main.py
index 0438961..72d3af2 100644
--- a/main.py
+++ b/main.py
@@ -9,7 +9,7 @@ app.config['DEBUG'] = True
 @app.route('/')
 def hello():
     """Return a friendly HTTP greeting."""
-    return 'Hello World!'
+    return 'Hello Python!'


 @app.errorhandler(404)

インデックスに編集した main.py を追加

$ git add main.py

コミット

$ git commit -m 'test edit'

Cloud Repository に push

$ git push -u origin master

Cloud Repository を GAE アプリに反映

Google Cloud Shell を開始

Google Developers Console にアクセス

プロジェクトを選択

上部にあるナビゲーションバーで Cloud Shell のアイコンをクリック

Cloud Shell でプロジェクトのディレクトリに移動

$ cd src/mytest-20161229/

Cloud Repository からクローン

$ gcloud source repos clone python-gae-quickstart --project=mytest-20161229

ディレクトリを確認

$ ls -la
total 16
drwxr-xr-x 4 fishrimper fishrimper 4096 Jan 28 23:29 .
drwxr-xr-x 4 fishrimper fishrimper 4096 Jan 28 16:03 ..
drwxr-xr-x 4 fishrimper fishrimper 4096 Jan 28 23:29 python-gae-quickstart
drwxr-xr-x 4 fishrimper fishrimper 4096 Jan 28 22:31 python_gae_quickstart-2016-12-29-22-39
  • python-gae-quickstart/ が今回クローンしたディレクトリ
  • python_gae_quickstart-2016-12-29-22-39/ が前回クローンしたディレクトリ

今回クローンしたディレクトリを確認

$ cd python-gae-quickstart/

$ ls -la
total 60
drwxr-xr-x 4 fishrimper fishrimper  4096 Jan 28 23:29 .
drwxr-xr-x 4 fishrimper fishrimper  4096 Jan 28 23:29 ..
-rw-r--r-- 1 fishrimper fishrimper   247 Jan 28 23:29 appengine_config.py
-rw-r--r-- 1 fishrimper fishrimper   170 Jan 28 23:29 app.yaml
-rw-r--r-- 1 fishrimper fishrimper  3045 Jan 28 23:29 CONTRIB.md
drwxr-xr-x 8 fishrimper fishrimper  4096 Jan 28 23:29 .git
drwxr-xr-x 4 fishrimper fishrimper  4096 Jan 28 23:29 lib
-rw-r--r-- 1 fishrimper fishrimper 11357 Jan 28 23:29 LICENSE
-rw-r--r-- 1 fishrimper fishrimper   425 Jan 28 23:29 main.py
-rw-r--r-- 1 fishrimper fishrimper   342 Jan 28 23:29 .playground
-rw-r--r-- 1 fishrimper fishrimper  2761 Jan 28 23:29 README.md
-rw-r--r-- 1 fishrimper fishrimper   275 Jan 28 23:29 requirements.txt
-rw-r--r-- 1 fishrimper fishrimper  2812 Jan 28 23:29 vendor.py

$ cat main.py
from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = True

# Note: We don't need to call run() since our application is embedded within
# the App Engine WSGI application server.


@app.route('/')
def hello():
    """Return a friendly HTTP greeting."""
    return 'Hello Python!'


@app.errorhandler(404)
def page_not_found(e):
    """Return a custom 404 error."""
    return 'Sorry, nothing at this URL.', 404

アプリをテスト

プレビューインスタンスの開始

$ dev_appserver.py ./app.yaml

「ウェブでプレビュー」でアプリをプレビュー

Cloud Shell 上部の「ウェブでプレビュー」アイコンをクリック

「ポート上でプレビュー 8080」を選択

ブラウザでプレビューが開かれ、「Hello Python!」と表示されました。

プレビューインスタンスの終了

Cloud Shell で Ctrl+C キーを押して、アプリケーションのインスタンスを終了

アプリをデプロイ

$ gcloud app deploy app.yaml --project mytest-20161229
You are about to deploy the following services:
 - mytest-20161229/default/20170128t234354 (from [/home/fishrimper/src/mytest-20161229/python-gae-quickstart/app.yaml])
     Deploying to URL: [https://mytest-20161229.appspot.com]
Do you want to continue (Y/n)?

Y 入力して続けました。

変更されたこと確認

$ w3m -dump https://mytest-20161229.appspot.com
Hello Python!

2017年1月8日日曜日

LXC ホストのディレクトリをコンテナでマウント

環境

Ubuntu 16.04 LTS (Xenial) Server

LXC ホストの /some/where/dir ディレクトリを lxc_ubuntu コンテナの /mnt/test ディレクトリにマウントします。

コンテナで /mnt/test マウントポイントを作成

$ sudo mkdir /mnt/test

ホストで /some/where/dir ディレクトリ作成

$ sudo mkdir -p /some/where/dir

ホストでコンテナの config ファイルの最後に以下追加

# pwd
/var/lib/lxc/lxc_ubuntu

# diff -u config.org config
--- config.org  2017-01-08 20:14:33.727390784 +0900
+++ config      2017-01-08 20:16:04.865214903 +0900
@@ -21,3 +21,5 @@
 lxc.network.link = lxcbr0
 lxc.network.flags = up
 lxc.network.hwaddr = 00:16:3e:22:22:ef
+
+lxc.mount.entry = /some/where/dir mnt/test none bind,create=dir 0 0

コンテナを再起動すると以下のようにマウントされました。

$ mount | grep test
/dev/sda1 on /mnt/test type ext4 (rw,relatime,errors=remount-ro,data=ordered)

LXC ホスト OS 起動時にコンテナも自動起動

環境

Ubuntu 16.04 LTS (Xenial) Server

LXC コンテナをリストして確認すると、デフォルトでは AUTOSTART が 0 となっておりホスト OS 起動時にコンテナはシャットダウンされています。

$ sudo lxc-ls --fancy
NAME       STATE   AUTOSTART GROUPS IPV4 IPV6
lxc_clone  STOPPED 0         -      -    -
lxc_ubuntu STOPPED 0         -      -    -

lxc_ubuntu コンテナの AUTOSTART を 1 にし、ホスト OS 起動時に自動起動するようにします。

コンテナの config ファイルの最後に lxc.start.auto = 1 を追加

# pwd
/var/lib/lxc/lxc_ubuntu

# diff -u config.org config
--- config.org  2017-01-02 15:30:59.557679188 +0900
+++ config      2017-01-08 17:49:43.151352672 +0900
@@ -21,3 +21,5 @@
 lxc.network.link = lxcbr0
 lxc.network.flags = up
 lxc.network.hwaddr = 00:16:3e:22:22:ef
+
+lxc.start.auto = 1

AUTOSTART が 1 になりました。

$ sudo lxc-ls --fancy
NAME       STATE   AUTOSTART GROUPS IPV4 IPV6
lxc_clone  STOPPED 0         -      -    -
lxc_ubuntu STOPPED 1         -      -    -

ホスト OS を再起動すると、lxc_ubuntu コンテナも起動しています。

$ sudo lxc-ls --fancy
NAME       STATE   AUTOSTART GROUPS IPV4      IPV6
lxc_clone  STOPPED 0         -      -         -
lxc_ubuntu RUNNING 1         -      10.0.3.69 -

2017年1月5日木曜日

Heroku で Python3 で Bottle アプリ

母艦の環境

  • Ubuntu 16.04.1 LTS (xenial)

パッケージをインストール

パッケージをインストール

$ sudo apt install virtualenv
$ sudo apt install git
$ sudo apt install curl
$ sudo apt install w3m
$ sudo apt install software-properties-common

Heroku のリポジトリを追加

$ sudo add-apt-repository "deb https://cli-assets.heroku.com/branches/stable/apt ./"
$ curl -L https://cli-assets.heroku.com/apt/release.key | sudo apt-key add -
$ sudo apt update

Heroku パッケージをインストール

$ sudo apt install heroku

Heroku にアプリを作成

Heroku にログイン

$ heroku login
  • 事前に登録したメールアドレスとパスワードを入力

アプリを作成

$ heroku create --app testapp-20170104
Creating ? testapp-20170104... done
https://testapp-20170104.herokuapp.com/ | https://git.heroku.com/testapp-20170104.git

Heroku にデプロイするアプリのファイルを準備

アプリケーション用の virtualenv を作成してアクティベート

$ virtualenv --python python3 testenv
$ source testenv/bin/activate

以下、virtualenv 環境下で実施します。

Python3 パッケージインストール

$ pip3 install gunicorn
$ pip3 install bottle

リポジトリをクローン

$ git clone https://git.heroku.com/testapp-20170104.git
Cloning into 'testapp-20170104'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

$ ls -la
total 16
drwxrwxr-x 4 ubuntu ubuntu 4096 Jan  4 17:26 .
drwxrwxr-x 5 ubuntu ubuntu 4096 Jan  4 17:10 ..
drwxrwxr-x 3 ubuntu ubuntu 4096 Jan  4 17:26 testapp-20170104
drwxrwxr-x 5 ubuntu ubuntu 4096 Jan  4 17:25 testenv

クローンした git リポジトリに移動

$ cd testapp-20170104/

Bottle アプリを用意

$ cat testapp.py
import sys
from bottle import route, default_app

@route('/')
def index():
  sHtml = '''
<html><body><pre>
=== sys.version ===
{}
===================
</pre></body></html>
'''.format(sys.version)

  return sHtml

appfunc = default_app()

Procfile を用意

$ cat Procfile
web: gunicorn testapp:appfunc --log-file -

requirements.txt 作成

$ pip3 freeze | egrep -v '^pkg-resources==' > requirements.txt

$ cat requirements.txt
bottle==0.12.11
gunicorn==19.6.0

ローカルでアプリをテスト

ローカルでアプリを起動

$ heroku local web
[WARN] No ENV file found
3:27:48 PM web.1 |  [2017-01-04 15:27:48 +0900] [6740] [INFO] Starting gunicorn 19.6.0
3:27:48 PM web.1 |  [2017-01-04 15:27:48 +0900] [6740] [INFO] Listening at: http://0.0.0.0:5000 (6740)
3:27:48 PM web.1 |  [2017-01-04 15:27:48 +0900] [6740] [INFO] Using worker: sync
3:27:48 PM web.1 |  [2017-01-04 15:27:48 +0900] [6774] [INFO] Booting worker with pid: 6774

起動メッセージから 5000番ポートであることがわかるので、別のターミナルを開き w3m で接続してみる (virtualenv 環境でなくても良いです)

$ w3m -dump http://localhost:5000/
=== sys.version ===
3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609]
===================
  • ローカルで起動した Heroku アプリが python-3.5.2 で実行されました。

Ctrl-C でアプリを終了

virtualenv 環境を終了

$ deactivate

Heroku にアプリをデプロイ

クローンしたリポジトリのディレクトリに移動

ローカルのアプリは Python-3.5.2 で実行されましたが、 https://devcenter.heroku.com/articles/python-runtimes を読むと Heroku での Python3 実行環境は python-3.6.0 とのことです。

runtime.txt で python-3.6.0 を指定

$ cat runtime.txt
python-3.6.0

ディレクトリは以下のようになっています。

$ ls -la
total 32
drwxrwxr-x 4 ubuntu ubuntu 4096 Jan  4 18:06 .
drwxrwxr-x 4 ubuntu ubuntu 4096 Jan  4 17:26 ..
drwxrwxr-x 8 ubuntu ubuntu 4096 Jan  4 17:59 .git
-rw-rw-r-- 1 ubuntu ubuntu   43 Jan  4 17:29 Procfile
drwxrwxr-x 2 ubuntu ubuntu 4096 Jan  4 17:40 __pycache__
-rw-rw-r-- 1 ubuntu ubuntu   33 Jan  4 17:58 requirements.txt
-rw-rw-r-- 1 ubuntu ubuntu   13 Jan  4 18:06 runtime.txt
-rwxr--r-- 1 ubuntu ubuntu  238 Jan  4 17:39 testapp.py

git アカウント情報登録

$ git config --global user.email "testuser@localdomain"
$ git config --global user.name "testuser"

git リポジトリにファイルを追加してコミット

$ git add Procfile
$ git add requirements.txt
$ git add runtime.txt
$ git add testapp.py
$ git commit -m 'initial commit'

デプロイ

$ git push origin master

w3m で確認

$ w3m -dump https://testapp-20170104.herokuapp.com/
=== sys.version ===
3.6.0 (default, Dec 24 2016, 04:08:05)
[GCC 4.8.4]
===================
  • Python-3.6.0 で実行されました。


2017年1月2日月曜日

LXC コンテナをクローンしてみました

環境

  • Ubuntu 16.04.1 LTS (xenial) Server

クローン前のコンテナの状態

$ sudo ls -la /var/lib/lxc
total 12
drwx------  3 root root 4096 Jan  2 14:56 .
drwxr-xr-x 45 root root 4096 Jan  2 14:52 ..
drwxrwx---  3 root root 4096 Jan  2 15:30 lxc_ubuntu

$ sudo lxc-ls --fancy
NAME       STATE   AUTOSTART GROUPS IPV4 IPV6
lxc_ubuntu STOPPED 0         -      -    -
  • クローン元のコンテナとして lxc_ubuntu を使用します。
  • クローン元の lxc_ubuntu は停止している必要があるとのことです。

lxc_ubuntu をクローン元として lxc_clone コンテナを作成

$ time sudo lxc-copy --name lxc_ubuntu --newname lxc_clone

real    1m33.688s
user    0m2.404s
sys     0m40.980s
  • 以前は lxc-clone コマンドでクローンを作成していたようですが、最近は lxc-copy コマンドを使うようです。

クローン後のコンテナの状態

$ sudo ls -la /var/lib/lxc
total 16
drwx------  4 root root 4096 Jan  2 17:25 .
drwxr-xr-x 45 root root 4096 Jan  2 14:52 ..
drwxrwx---  3 root root 4096 Jan  2 17:25 lxc_clone
drwxrwx---  3 root root 4096 Jan  2 15:30 lxc_ubuntu

$ sudo lxc-ls --fancy
NAME       STATE   AUTOSTART GROUPS IPV4 IPV6
lxc_clone  STOPPED 0         -      -    -
lxc_ubuntu STOPPED 0         -      -    -