くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

2018年07月

VirtualBox ホストOS側からゲストOS側のサイトにアクセス

タイトル通り。通常のままだとできない。やり方は色々ある模様。

今回はNAT構成でポートフォワードの設定を作ってやる。ゲストOS側のサイトはDockerでnginxをリバースプロキシ(localhost:80/myfront ⇒ nuxt)にしてnuxtにつなぐ構成のサイト。

VirtualBoxの仮想マシン⇒設定からネットワーク開いて、NAT選択と高度⇒ポートフォワーディング。

sample01

そしたらルールの追加押して、ホスト側が送るIPとポート、ゲスト側が受けるIPとポートを指定。

sample02

これで、ホスト側のブラウザで「http://127.0.0.1:9999」みたいにしてやればつながる。

Pythonで共有ライブラリ(hoge.so)を呼ぶ

CentoOS。Pythonから***.soみたいな共有ライブラリを呼ぶ必要があったのでちょっと調べた。Python3.6。

呼び方は↓。

import ctypes

LIB_PATH = '/hoge/fuga/libmodule.so'
lib = ctypes.cdll.LoadLibrary(LIB_PATH )

res = lib.hogefunc()

#intの引数とるやつ
arg_int= ctypes.c_int(10)
res = lib.fugefunc(arg_int)

関数呼ぶのは上で行けるんだけど、引数が結構ややこしい。基本的には公式のctype見ればいいんだけども。やっかいなのが「char *」。ポインタの場合は↓の感じ。

str="some args str"
strb=bytes(str , encoding='utf-8', errors='replace')
strp=ctypes.c_char_p(strb )

res = lib.mogefunc(strp)

一回バイト配列に変換してからポインタに変換しないとダメみたいですよ。

CentOS Yum / Git / Curl プロキシの設定

プロキシ環境でやる場合。ユーザ認証付きで。他にもあるので今度足す。

■Yum
vi /etc/yum.conf

proxy = http://000.000.000.000:8080
proxy_username = hogeuser
proxy_password = fugapass

■Git
git config --global http.proxy http://hogeuser:fugapass@000.000.000.000:8080
git config --global https.proxy http://hogeuser:fugapass@000.000.000.000:8080
git config --global url."https://".insteadOf git://

確認
git config --list

■Wget
vi /etc/wgetrc

http_proxy=http.proxy http://hogeuser:fugapass@000.000.000.000:8080
https_proxy=http.proxy http://hogeuser:fugapass@000.000.000.000:8080
ftp_proxy=http.proxy http://hogeuser:fugapass@000.000.000.000:8080

■Curl
curl -U hogeuser:fugapass -x 000.000.000.000:8080 -L http://mirrorlist.centos.org

loadtestで性能確認

性能系の確認をしたい場合に使うやつ。nodeで動くので、node必須。公式?はココ

インストール。CentOS7。nodeとnpm入れてから。入ってない場合はコッチ参照

npm install -g loadtest

で、色々オプションがあるんだけど、とりあえずの使用は↓

loadtest [-n requests] [-c concurrency] URL

ex.
loadtest -n 200 -c 10 http://localhost/hoge

使いそうなオプションは↓

-n requests 送るリクエストの数。-c指定してる場合にリクエストの総数がパラメータよりも大きくなる可能性があるとのこと。その場合は最初のn個だけレポートするらし。
-c concurrency 擬似的にクライアントをここで指定した個数分作って、並列処理するらし。 プロセス的に分けて並列してるわけではない模様。応答が返ってくる前に2個目のリクエストが送信される場合もあるってさ。
-t timelimit リクエスト送り続ける秒数。応答が返ってきてなくても終わらせるってさ。
-C cookie-name=value cookie付けたい場合。複数ある場合は繰り返して書けって事らし。
-H header:value ヘッダーつけたい場合。jwtのテストとかで使えそう?「-h ”Authorization: JWT token-value"」的に。複数ある場合は繰り返して書けってさ。
-P POST-body ポストの中身。「-P '{"key": "a9acf03f"}'」みたいな。
-m method メソッドの指定。デフォはGET。POSTにしたい時⇒「-m POST」
-T content-type content-typeですね。デフォはtext/plain。
--data POST some variables フォーム送信的な事やるときはこれかな?⇒の感じで使えってさ。「--data '{"username": "test", "password": "test"}' -T 'application/x-www-form-urlencoded' -m POST」。これやるときは「-m POST」 と -Tは必須っぽ。
--rps requestsPerSecond これ使いそー。1秒間あたりに何個リクエスト出すかを指定する。「--rps 0.5」は2秒毎に1リクエストらし。-cと合わせる場合、並列の個数毎に効くんじゃなくて、全体としての扱いになる模様。-c 10とかやって場合に一つ一つ毎にrpsが効くわけではないと。で、あまりに並列度低いとrps満たせなくなるからそれなりに考えてねってことらしい。

他にもいろいろあるので詳しくは公式参照

例えば、10個のクライアントで1秒間にトータル100リクエスト(1クライアント10リクエスト/秒想定)出す状態で10秒間動かす場合は↓の感じ。

loadtest -t 10 -c 10 --rps 100 http://localhost/hoge

で、動かすと色々出てくるんだけど見るのは↓あたりかな。

#1秒間に送信できたリクエスト数
Requests per second: 10
#平均待ち時間
Mean latency:        6.4 ms
#待ち時間の分布割合。↓だと50%は5msで帰ってきてるってことかしら?
Percentage of the requests served within a certain time
  50%      5 ms
  90%      10 ms
  95%      12 ms
  99%      23 ms
 100%      23 ms (longest request)

あと↓の感じで(公式サンプル)、javascriptとして普通に組み込めるからテスト用にモジュール化しておけば、自動実行とか組み込めそうですね。。。

const loadtest = require('loadtest');
const options = {
    url: 'http://localhost:8000',
    maxRequests: 1000,
};
loadtest.loadTest(options, function(error, result)
{
    if (error)
    {
        return console.error('Got an error: %s', error);
    }
    console.log('Tests run successfully');
});

CentOS7にNode.jsをインスト

やり方まとめ。公式はここ

yumでインストールする場合。楽にやりたい場合はEPELのリポジトリを使わないとダメそう。

sudo yum -y install epel-release
or
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

sudo yum install nodejs npm --enablerepo=epel

これでインストールされるバージョンは結構古い。現状だと↓。

node -v
⇒v6.14.3
npm -v
⇒3.10.10

nodeのバージョン管理ツール的なnvm使うやり方がよさそう。やり方はココ見た方が早い。

CentOS7 Redis4 Python3で性能確認

VirtualBox上のCentOS7にRedis4入れてPtyhonから呼んでみたときの性能回り。

VirtualBoxはRAM4GB、CPU:1コア,2.9G。

まず、接続。コネクションプール使うのがあるので比較。

import time
import redis

#コネクションプール使用で1万回接続⇒0.05472540855407715
t1 = time.time()
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, password='hogepass')
for i in range(10000):
    r = redis.Redis(connection_pool=pool)
print(time.time() - t1)

#普通に1万回接続⇒0.2304081916809082
t1 = time.time()
for i in range(10000):
    r = redis.Redis(host='127.0.0.1', port=6379, password='hogepass')
print(time.time() - t1)

#4.5倍くらいプールの方が早い?

で、なんでか普通に接続の方を先にやるとプールの方が遅くなる。なんじゃらほい。

キーバリュの更新。ランダム文字の10万文字をバリューにして10000回更新

import time
import redis
import string
import random

def randomCharacter(n):
    c = string.ascii_lowercase + string.ascii_uppercase + string.digits
    return ''.join([random.choice(c) for i in range(n)])

databody = randomCharacter(100000)


t1 = time.time()
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, password='hogepass')
r = redis.Redis(connection_pool=pool)
for i in range(10000):
    r.set(i,databody)
print(time.time() - t1)

#1回目:3.6718790531158447
#2回目:3.044043779373169
#3回目:2.0042741298675537
#4回目:2.015092134475708

初回(追加)ベースで考えると、10万文字のデータ更新で1件0.3msってところ。

索引。1万文字のバリューで1万件のデータをを1000回1件索引

t1 = time.time()
for i in range(1000):
    r.get(i)
print(time.time() - t1)

# 0.10848879814147949

1回あたり、0.1msと言った感じ。

おまけ

コネクションプールと普通の接続でmonitorの結果

import redis

pool = redis.ConnectionPool(host='127.0.0.1', port=6379, password='hogepass')
#プール1回目
r = redis.Redis(connection_pool=pool)
r.set('pool1','hoge1')#プールの場合はここでAuthのコマンド送ってる
r.get('pool1')
#プール2回目
r = redis.Redis(connection_pool=pool)
r.set('pool2','hoge2')
r.get('pool2')
#普通の1回目
r = redis.Redis(host='127.0.0.1', port=6379, password='hogepass')
r.set('not pool1','fuga1')
r.get('not pool1')
#普通の2回目
r = redis.Redis(host='127.0.0.1', port=6379, password='hogepass')
r.set('not pool2','fuga2')
r.get('not pool2')

上のmonitor結果

[0 127.0.0.1:58564] "AUTH" "hogepass"
[0 127.0.0.1:58564] "SET" "pool1" "hoge1"
[0 127.0.0.1:58564] "GET" "pool1"
[0 127.0.0.1:58564] "SET" "pool2" "hoge2"
[0 127.0.0.1:58564] "GET" "pool2"
[0 127.0.0.1:58566] "AUTH" "hogepass"
[0 127.0.0.1:58566] "SET" "not pool1" "fuga1"
[0 127.0.0.1:58566] "GET" "not pool1"
[0 127.0.0.1:58568] "AUTH" "hogepass"
[0 127.0.0.1:58568] "SET" "not pool2" "fuga2"
[0 127.0.0.1:58568] "GET" "not pool2"

コネクションプール使ってる方はやっぱ、つなぎ直しはしてませんね。つか繋ぎっぱなしになるんだろか。接続解除的な何かあったかな。あと、プールの場合は最初のSetの時にAuthコマンドはいてるっぽいですね。。。

CentOS7 + Redis

CentOS7でRedis4インストール。ググるとCentOS6だったりRedis3だったり色々なのでまとめ。

公式に載ってる通りにまずインストール。

#作業はRootで
#適当なディレクト内で実行
wget http://download.redis.io/releases/redis-4.0.10.tar.gz
tar xzf redis-4.0.10.tar.gz
cd redis-4.0.10
make

#起動確認
src/redis-server

#インストール先はデフォで⇒ /usr/local/bin
make install

redisのユーザとグループを作る。

groupadd redis
useradd -s /sbin/nologin -M -g redis redis

設定・ログとかとか用のディレクトリとパーミッション

mkdir /etc/redis
mkdir /var/log/redis

chmod 755 /etc/redis
chmod 755 /var/log/redis

chown redis:redis /etc/redis 
chown redis:redis /var/log/redis

設定ファイルの雛形コピーして修正。

#最初に展開したredis-4.0.10の中
cp redis.conf /etc/redis/redis.conf_org #元ファイルをなんとなく
cp redis.conf /etc/redis/redis6379.conf

#編集
vi /etc/redis/redis6379.conf

#修正内容は↓
daemonize no
supervised auto
logfile /var/log/redis/redis6379.log
dir /var/log/redis
requirepass hogepass
maxclients 1024 

起動確認。

/usr/local/bin/redis-server /etc/redis/redis6379.conf

#別のターミナルで
redis-cli
auth hogepass
ping
quit

自動起動の設定。

#Unitの設定ファイル
vi /etc/systemd/system/redis6379.service
#中身
[Unit]
Description=Redis

[Service]
Type=simple
ExecStart=/usr/local/bin/redis-server /etc/redis/redis6379.conf
ExecStop=/usr/local/bin/redis-cli -p 6379 -a hogepass shutdown
User=redis
Group=redis

[Install]
WantedBy=multi-user.target


#起動確認
systemctl daemon-reload
systemctl start redis6379
systemctl stop redis6379

#サービス化の設定
systemctl enable redis6379

で、自動起動にして再起動すると上手くいかない場合がある。rootで色々起動確認しながらやると、DBのダンプファイルとかログファイルがrootで作成されてしまうので、自動起動時のredisユーザだと触れなくて落ちてる模様。その場合は、上記の設定で言うと「/var/log/redis」の中のファイル丸ごと消して再起動すればOK。

systemctlで起動したときのログは「 journalctl -f -u redis6379」みたいな感じでやると見れる。

参考

CentOS7でApacheでDjango動かすまで

まーはまったので、残しとく。ApacheでDjango動かすまでのまとめ。Python3.6とDjango入れるのはこっちがメイン

まず、Python3.6入れる。

#RPM持ってくる
sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm
#インスト
sudo yum -y install python36u
sudo yum -y install python36u-pip
sudo yum -y install python36u-devel

Apache入れる

sudo yum install -y httpd
sudo yum install -y httpd httpd-devel

で、ここから人によると思うんだけど、自分はユーザのホームに「public_html」を作ってそこにDjangoのプロジェクト入れる感じでやる。

#ユーザのホームで
mkdir public_html
#ホームディレクトリのパーミッションを変える
chmod 701 /home/hogeusr

で、ホームディレクト内のディレクトリ使う場合は、ホームディレクトリそのものの、パーミッションで他ユーザの実行権限つけないと動かない。これのやり方はなんか他にないか今度調べよ。

そしたら、とりあえずDjangoのプロジェクト作って確認しておく。

cd ~/public_html/
#仮想環境作る
python3.6 -m venv pyenv
#仮想環境に切り替え
cd pyenv
source bin/activate
#pipの更新
pip install --upgrade pip
#Djangoのインスト
pip install django
#プロジェクト作る
django-admin startproject mysite
#とりあえず実行
cd mysite
python manage.py runserver
#↓にブラウザでアクセス
http://127.0.0.1:8000/

そしたら、mod_wsgiをインストしておく。

#pipで入れないとダメらしい。あと、仮想環境上でやらないとダメ。
pip install mod_wsgi
#入ったモジュールのパスを表示→メモっとく(後で使う)
find /home/hogeusr/public_html/ -name 'mod_*.so'
#仮想環境抜ける
deactivate

設定ファイルを作る

#mod_wsgiの読み込み設定(上でfindしたやつ)
sudo vi /etc/httpd/conf.modules.d/mod_wsgi.conf
LoadModule wsgi_module /home/hogeusr/public_html/pyenv/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so

#wsgiに読ませるDjangoの設定
sudo vi /etc/httpd/conf.d/django.conf
#ファイルの中身は↓(パスは適宜変更)
WSGIPythonHome /home/hogeusr/public_html/pyenv
WSGIScriptAlias / /home/hogeusr/public_html/pyenv/mysite/mysite/wsgi.py
WSGIPythonPath /home/hogeusr/public_html/pyenv/mysite:/home/hogeusr/public_html/pyenv/lib/python3.6/site-packages

<Directory /home/hogeusr/public_html/pyenv/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

で、ここまでやった状態で「sudo systemctl restart httpd」を実行するとSELinuxに拒否られる。なので、この辺の設定を次にする。

sudo setsebool -P httpd_enable_homedirs 1
sudo setsebool -P httpd_unified 1
sudo systemctl restart httpd
#↓にブラウザでアクセス
http://localhost

これでDjangoの初画面がでるはず。

WSGIPythonHomeは仮想環境のディレクトリを指定。WSGIScriptAliasはここで指定したURLに来た時にどのWsgiスクリプト動かすか。WSGIPythonPathはWSGIで動かした時に読ませるPythonPath。色んなモジュール読み込みで必要らしい。PythonPathについてはココのブログが分かりやすい。公式はこっち

Apacheで動かすときのDjangoの公式はコッチ

やっててエラーが出たら「/etc/httpd/logs/error_log」にヒントが出るので見ながらアレコレやるしかあるまい。見たエラー的には↓

Fatal Python error: Py_Initialize: Unable to get the locale encoding.
→ WSGIPythonPath のパスが違う。homeティレクトリのパーミッション。

Target WSGI script not found or unable to stat: /home/hogeusr/public_html/pyenv/mysite/wsgi.py
→ パスが違う

自分は他のセキュリティ系の設定はやらなくてもlocalhostで動いたけど、ほんとはやらないとダメなのかな?下の内容。

#↓のファイルでALLOWED_HOSTS=['*']にしておく。
#全OKの設定なのでホントは色々考えないとダメだろね。
vi ~/public_html/pyenv/mysite/mysite/settings.py

あとはファイヤーウォール。面倒なので、一回切ればいいじゃないだろか。。。

systemctl stop firewalld

VirtualBoxとCentOS

VirtualBoxでCentOS使うときの最初にやるとこ。

CentOS-7-x86_64-DVD-1804.iso使ってるけど、なんかGUIが入らないのでGUI入れる。(最小構成でインストしてた・・・)あと、マウス統合と画面リサイズの対応。

まずCentOSのインストール後にGNome入れる。

#yumの更新
yum -y update

#GNOME入れる(結構時間かかる)
yum groupinstall "GNOME Desktop"

#GUI上げる
startx

起動時に自動的にGUI化するのも設定できるけど、個人的に最初はコンソールがいいので、このまま。 GUI上げたら、ターミナル上げて↓。

yum -y install kernel-devel gcc

そしたら、「デバイス > CD/DVDデバイス > Guest Additions のCDイメージを挿入…」→ポップアップ上がるのでRUNを選択。そしたら再起動「shutdown -r now」。

sample01

上がったらGUI上げて↓。

クリップボードの共有

sample02

で、このままだと、VirtuaBoxからホスト側の画面にカーソル移すには”右下”のCtrl押さないとダメなので、マウス統合する。なんでか、下の感じで画面右下のディスプレイを一回操作しないとマウス統合が効かない。なんでだろね。

sample03

画面のリサイズはパワーオフして一回完全に落とさないと効いてくれなかった。なんでだろね。

2018/8/13追記

まとめ。

CentOSのisoからインストールでGNOME選んでインスト。
上がったら、ターミナルで↓。

yum update
yum -y install kernel-devel gcc

「デバイス > CD/DVDデバイス > Guest Additions のCDイメージを挿入…」
ポップアップ上がったら実行して再起動

これで上手くいった。yum updateしないとダメ見たい。Additions実行してもダメな場合は、もっかいyum updateしてから、Additions実行すると上手くいく。2回目に実行するときはデスクトップにCDのアイコン出来てると思うので、アイコンダブクリ⇒ディレクトリ開いてメニューの中に実行みたいなボタンが出てくるからそれで実行。

目的と手段

自分SEやってるんですが、昔より色んなOSとかフレームワークとかツールとか触る事が増えた。その中でなんかモヤモヤするものがあるので愚痴っておきたい。こういうチラ裏みたいなの、初めて書くかも。今まで書いてきた奴もたいがい便所の落書きみたいなもんですが。。。

一言で言うと、
俺が考えたいのは業務ロジックとかビジネスロジックであって、apacheのパーミッションウンヌンじゃねーんだよ。

そういうのがカッコいいと思っていた時期が自分にもありました。

「yumじゃなくてpipで入れないとダメー」とか見たり聞いたりすると、ほんとしょーもねーな。と思う。

ユーザに膨大な量の経験と知識を執拗に迫るシステムって割とクソだと思うのです。主体が色々あるから複雑怪奇になるのも分かるし、どうにかしようとしてる人もたくさんいるのは分かる。でもクソ。

で、その状況を当たり前とか思ってたり、ドヤ顔で話してる人達。この分かりにくさを受け入れてどーするよ。システムとかツールなんて文字通りただの道具だろ。

とか言いつつ、自分が作ってるモノはどうなのかと。使ってくれる人のやりたい事を、迷ったりハマッたりしないで出来るようにしないとダメですよね。

まーでも、こういう難しさを使いたい人の替りにやるのがエンジニアとしてのサービスかとも思う。そういう事にサービスとしての対価が生まれるんだよね。けど、こういう難しさを分かってない人(経営層とかとかとか)らは技術者の価値を低く見てるようにすごく感じたりもする。出来る人たちはこういう価値を分かってるから投資もちゃんとやるよね。。。

何が言いたいのか分かんなくなった。とりあえず難しいことを誇るのはどうかと思う。

問合せ