togatttiのエンジニアメモ

過度な期待はしないでください.

parallel-slurpで、ファイルを並列で取得する

複数のホストから、ファイルをダウンロードする必要があったので、方法を調べた。

parallel-slurp(pslurp)という便利なものがあったので、使うことにした。

インストール

OSは、Ubuntuなので、APTでインストールする。

# apt install pssh

manを読むと、やりたことが書かれてる。

        PARALLEL-SLURP(1)                                                                                            PARALLEL-SLURP(1)

NAME
       parallel-slurp - copy files from listed hosts

SYNOPSIS
       parallel-slurp [OPTIONS] -h hosts.txt -L destdir remote local

DESCRIPTION
       pssh provides a number of commands for executing against a group of computers, using SSH. It´s most useful for
       operating on clusters of homogenously-configured hosts.

       parallel-slurp gathers specified files from hosts you listed.
(snip)

使い方

対象ホストのリストを用意する。

$ cd /home/admin/
$ cat file_list
a.example.com
b.example.com
c.example.com

ダウンロードしたファイル用のディレクトリを作成する。

$ mkdir downloads

parallel-slurpを実行する。

$ parallel-slurp -ladmin -h file_list -p 3 -L /home/admin/downloads /var/log/http_access.log http_access.log

引数の説明を簡単にする。

  • -lは、作業ユーザ
  • -hは、対象ホストのリスト
  • -pは、並列処理数
  • -Lは、ダウンロードしたファイルを置くディレクト

そのあとの引数は

  • ダウンロードするファイルの絶対パス
  • ダウンロードした際のファイルの名前

実行するとディレクトリは次のようになる。

$ tree downloads/
downloads/
├── a.example.com
│   └── http_access.log
├── b.example.com
│   └── http_access.log
└── c.example.com
    └── http_access.log

3 directories, 3 files

browsertimeで、Webページの描画過程を録画する

browsertimeを使い、Webページのロード時間を計測しながら、描画過程を録画する。

うまくいくとこんな感じで、録画できる。

browsertimeで生成されたmp4ファイル、HTMLの記述例などは、GitHubに置いた。

https://github.com/kentatogashi/example-browsertime

browsertimeの実行方法

OSは、Ubuntu16.04を使う。

Dockerを入れる。

# apt update 
# apt install -y docker.io

browsertimeを実行する

# docker run --privileged --shm-size=1g --rm -v "$(pwd)":/browsertime-results sitespeedio/browsertime -n 1 -c cable --video --speedIndex 'https://www.yahoo.com'

実行すると、ディレクトリが生成され、動画や画像が格納される。

$ tree www.yahoo.com
www.yahoo.com
└── 2017-02-14T043457+0000
    ├── browsertime.har
    ├── browsertime.json
    └── video
        ├── 0.mp4
        └── images
            └── 0
                ├── ms_000000.jpg
                  (snip)
                 └── ms_007950.jpg

4 directories, 78 files

HTTP/1.1とHTTP/2の比較計測をする際に、はかどりそう。

あと、日本語サイトに対して、実行すると文字化けするので、ちょっと残念なところはある。

参考 - GitHub - sitespeedio/browsertime: Your browser, your page, your scripts!

外部サーバにSquid3でプロキシを立てる

プロキシを設定したときの走り書きです。

環境は、Ubuntu14.04.3 LTSです。

インストール

# apt-get install -y squid3

設定ファイル

/etc/squid3/squid.confをコピーして使う。特定のACLからの80と443ポートへのアクセスをフォワードするように 最低限の設定をする。

acl localnet src  ***.***.***.***/23
acl SSL_ports port 443
acl Safe_ports port 80
acl Safe_ports port 443
acl CONNECT method CONNECT

http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost
http_access allow localnet
http_access deny all
http_port 3128
cache_dir ufs /var/spool/squid3 600 16 256
coredump_dir /var/spool/squid3
refresh_pattern .       0   20% 4320
access_log /var/log/squid3/access.log common

再起動する。

# restart squid3

curlで、動作確認する。

ACLで許可したサーバからプロキシ経由でアクセスした場合

$ curl -I -x proxy.example.com:3128 -L blog.hatena.ne.jp
HTTP/1.1 302 Moved Temporarily
Cache-Control: private
Content-Type: text/html; charset=utf-8
Date: Sun, 08 Jan 2017 04:25:05 GMT
Location: https://www.hatena.ne.jp/login?location=http%3A%2F%2Fblog.hatena.ne.jp%2F
P3P: CP="OTI CUR OUR BUS STA"
Server: nginx
Set-Cookie: b=$1$hgANMQcX$tV164HRhox4dVoyOz9eGh1; expires=Sat, 03-Jan-2037 04:25:05 GMT; domain=hatena.ne.jp; path=/
Set-Cookie: sk=99c1e798a67850410e453590e89a8cc9025ffb7f; path=/
Vary: Accept-Language, Cookie
X-Content-Type-Options: nosniff
X-Dispatch: Hatena::Epic::Admin::Index#default
X-Frame-Options: DENY
X-Revision: 81eb8b22d9cef6ded0b861732d7ed075
X-Runtime: 0.007440
X-XSS-Protection: 1
X-Cache: MISS from ***********
X-Cache-Lookup: MISS from ***********:3128
Via: 1.1 **********(squid/3.3.8)
Connection: keep-alive

HTTP/1.1 200 Connection established

HTTP/1.1 200 OK
Server: nginx
Date: Sun, 08 Jan 2017 04:25:06 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 8393
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: no-cache
Pragma: no-cache
Vary: Accept-Language,Accept-Encoding,User-Agent
X-Frame-Options: SAMEORIGIN
X-Framework: Ridge/0.11 Plack/0.9982
X-Ridge-Dispatch: Hatena::WWW::Engine::Login#default
X-Runtime: 79ms
X-View-Runtime: 54ms
Set-Cookie: b=$1$nniOFGW0$4HjT61d1E1yqllw58ss1o/; path=/; expires=Sat, 03-Jan-37 04:25:05 GMT; domain=.hatena.ne.jp

ACLで許可しないサーバからプロキシ経由でアクセスした場合

$ curl -I -x proxy.example.com:3128 -L blog.hatena.ne.jp
HTTP/1.1 403 Forbidden
Server: squid/3.3.8
Mime-Version: 1.0
Date: Sun, 08 Jan 2017 04:31:45 GMT
Content-Type: text/html
Content-Length: 3186
X-Squid-Error: ERR_ACCESS_DENIED 0
Vary: Accept-Language
Content-Language: en
X-Cache: MISS from ******
X-Cache-Lookup: NONE from ******:3128
Via: 1.1 ****** (squid/3.3.8)
Connection: keep-alive

FreeBSD10のHTTP/2設定手順

FreeBSD10で、HTTP/2の検証をしようと思ったので、設定手順を残す。

Webサーバは、Apacheを使う。

環境

  • OS
    • FreeBSD10.3

必要なソフトのインストール

クリーンインストール後からの作業を想定しているので、

すでに稼動しているサーバとは手順が異なるかもしれない。

pkgツール

# pkg

perl、pcre

# pkg install perl5.22
# ln -s /usr/local/bin/perl5.22.3 /usr/local/bin/perl
# pkg install pcre

openssl

クライアントとサーバ間で、ALPNを使用するために、OpenSSLの1.0.2以上を入れる。

# mkdir /usr/local/src
# fetch --no-verify-peer https://www.openssl.org/source/openssl-1.0.2j.tar.gz
# tar xvfz openssl-1.0.2j
# cd /usr/local/src/openssl-1.0.2j
# ./config -fPIC —shared
# make && make install

共有ライブラリのパスを追加する。

# ldconfig -m /usr/local/ssl/lib

nghttp2

# fetch --no-verify-peer https://github.com/nghttp2/nghttp2/releases/download/v1.17.0/nghttp2-1.17.0.tar.gz
# tar xvfz nghttp2-1.17.0.tar.gz
# cd /usr/local/src/nghttp2-1.17.0

contrib/Makefileconfigfiles = nghttpx-init nghttpx.service nghttpx-upstart.confコメントアウトして、ビルドする。

# ./configure
# make && make install

apr、apr-util

apr

# fetch --no-verify-peer http://ftp.meisei-u.ac.jp/mirror/apache/dist//apr/apr-1.5.2.tar.gz
# tar xvfz apr-1.5.2.tar.gz
# cd /usr/local/src/apr-1.5.2
# ./configure
# make && make install

apr-util

# fetch --no-verify-peer http://ftp.meisei-u.ac.jp/mirror/apache/dist//apr/apr-util-1.5.4.tar.gz
# tar xvfz apr-util-1.5.4.tar.gz
# cd /usr/local/src/apr-util-1.5.4
# ./configure --with-apr=/usr/local/apr
# make && make install

Apache

# fetch --no-verify-peer http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//httpd/httpd-2.4.23.tar.gz
# tar xvfz
# cd /usr/local/src/httpd-2.4.23
# ./configure --prefix=/usr/local/etc/apache24 --with-included-apr=/usr/local --enable-ssl --with-ssl=/usr/local/ssl --with-nghttp2=/usr/local --enable-http2 --enable-so
# make && make install

VirtualHost設定

httpd.confを修正して、443をListen、mod_sslとmod_http2を有効にする。

また、バーチャルホストの設定ファイルは、/usr/local/etc/apache24/conf/virtual_host/以下に置くようにする。

@@ -50,6 +50,7 @@
 #
 #Listen 12.34.56.78:80
 Listen 80
+Listen 443

 #
 # Dynamic Shared Object (DSO) Support
@@ -128,8 +129,8 @@
 #LoadModule session_cookie_module modules/mod_session_cookie.so
 #LoadModule session_dbd_module modules/mod_session_dbd.so
 #LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
-#LoadModule ssl_module modules/mod_ssl.so
-#LoadModule http2_module modules/mod_http2.so
+LoadModule ssl_module modules/mod_ssl.so
+LoadModule http2_module modules/mod_http2.so
 #LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
 #LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
 #LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
@@ -490,5 +491,8 @@
 <IfModule ssl_module>
 SSLRandomSeed startup builtin
 SSLRandomSeed connect builtin
+SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
+SSLProtocol All -SSLv2 -SSLv3
 </IfModule>

+Include /usr/local/etc/apache24/conf/virtual_host/*.conf

バーチャルホスト側は、こんな感じにする。

# cat  /usr/local/etc/apache24/conf/virtual_host/togattti.example.com.conf
<VirtualHost 192.168.0.1:443>
    ServerName togattti.example.com
    ErrorLog logs/ssl_error_log
    SSLEngine on
    SSLCertificateFile "/usr/local/etc/ssl/my.crt"
    SSLCertificateKeyFile "/usr/local/etc/ssl/my.key"
    Protocols h2 http/1.1
    ProtocolsHonorOrder On
    DocumentRoot "/usr/local/etc/apache24/htdocs"
</VirtualHost>

SSL証明書を作る。

# mkdir /usr/local/etc/ssl
# openssl genrsa 2048 > /usr/local/etc/ssl/my.key
# openssl req -new -key my.key > /usr/local/etc/ssl/my.crt
# openssl x509 -days 3650 -req -signkey /usr/local/etc/ssl/my.key < /usr/local/etc/ssl/my.csr > /usr/local/etc/ssl/my.crt

Apacheを再起動する。

/usr/local/etc/apache24/bin/httpd -k restart

検証

Chromeで、開いて、デベロッパーツールのProtocol欄がh2になれば、問題なく設定できている。

f:id:togattti1990:20161215191248p:plain

ファイルの各行にUUIDを付加するスニペット

ログ収集ツールのfluentdのuuid_keyを使う場合、ログにUUIDを振る必要がある。

こんなときシェルスクリプトで、whileやfor、uuidgenを組み合わせて、追記していたが、 行が膨大な場合、処理の遅延が気になったので、C言語で処理するプログラムを書いた。

プログラム

Ubuntu環境で、動かした。

依存ライブラリをインストールする。

$ sudo apt install uuid-dev

Cのプログラムは、こんな感じ。

#include <stdio.h>
#include <string.h>
#include <uuid/uuid.h>

int main(int argc, char *argv[]) {
  FILE *source, *target;
  char line[256];
  uuid_t uuid;
  char uuid_str[37];
  int len;

  source = fopen(argv[1], "r");
  target = fopen(argv[2], "w");
  while(fgets(line, 256, source)) {
    len = strlen(line);
    if (line[len-1] == '\n') {
      line[len-1] = 0;
    }
    uuid_generate_time_safe(uuid);
    uuid_unparse_lower(uuid, uuid_str);
    fprintf(target, "%s %s\n", line, uuid_str);
  }
  fclose(source);
  fclose(target);
  return 0;
 }

コンパイルする。

$ gcc -o append_uuid append_uuid.c -luuid

ベンチマーク計測

比較用のファイルを用意する。

$ for i in `seq 10000`; do echo "abc" >> uuid_by_bash.txt; echo "abc" >> uuid_by_c.txt; done
$ wc -l uuid_by_bash.txt uuid_by_c.txt
10000 uuid_by_bash.txt
10000 uuid_by_c.txt
20000 total

まずは、Bashでやる場合(これがBashのベストプラクティスかどうかは知らない。。)

$ time cat uuid_by_bash.txt | while read line; do uuid=$(uuidgen); echo "$line $uuid" >> uuid_by_bash.txt.new; done

real    0m25.741s
user    0m1.268s
sys 0m7.632s
$ tail -1 uuid_by_bash.txt.new
abc 006b69fd-9ad0-4749-afe1-eef73c6ffad0

次は、Cで書いたプログラム。

$ time ./append_uuid uuid_by_c.txt uuid_by_c.txt.new
uuid_by_c.txt uuid_by_c.txt.new
real    0m0.020s
user    0m0.016s
sys 0m0.000s
$ tail -1 uuid_by_c.txt.new
abc d05dc0b5-bad5-11e6-81bd-000c291c1598

クソ速い。