お手軽並列処理




   斉藤 博文 (hi_saito@yk.rim.or.jp)
                      @hi_saito
最近の興味のあるところ
自宅でのスマホやタブレットを快適に利用したい。

●
  回線はそのままだけど、インターネット接続端末
  が増えて重くなってきたよね。
●
  スマホで表示される広告がうるさいよね。
●
  不意にタップしてしまうことがあるよね。


    そんな時こそ OSS の活躍の場
具体的には?
Fedora をサーバーにしていろいろ改善中。

●
  Web のキャッシュ              squid
●
  DNS のキャッシュ              dnsmasq
●
  広告の削除                   adzapper
●
  hosts, iptables の自動更新   cron


           なかなか快適です!
自宅の構成
                                              Web サーバー
  モデム
                                              DNS サーバー
                       iMac          Fedora
    1.5M ADSL                                 Proxy サーバー



 ルーター
    40M


                iPhone        iPhone    iPhone


WiFi ルーター        Wii           DS


                 Win           Win      Fedora
今日のお題
hosts ファイルの自動更新

●
  ローカルの hosts ファイルにブラックリストの書
  かれた hosts を入手してマージする。
●
  ちなみに、DNS キャッシュの dnsmasq が
  hosts を見てくれるので楽です。


        これをどう書くか?
やりたいことを書こう!
●
  今の hosts をバックアップ
●
  ブラックリストを入手する
●
  ブラックリストを hosts 形式にする
●
  新しい hosts を作る
●
  新しい host を上書きする
●
  以前の hosts との差分を取る
●
  古いバックアップを削除する

      書くだけなら、簡単ですね。
順序を決めよう!
  今の hosts をバックアップ

  ブラックリストを入手する

  ブラックリストを hosts 形式にする

  新しい hosts を作る

  新しい host を上書きする

  以前の hosts との差分を取る

  古いバックアップを削除する
並列処理できるかな?
  今の hosts をバックアップ

  ブラックリストを入手する

  ブラックリストを hosts 形式にする

  新しい hosts を作る

  新しい host を上書きする

  以前の hosts との差分を取る

  古いバックアップを削除する
グループ分けしよう!
       ●
         今の hosts をバックアップ
準備     ●
         ブラックリストを入手する
       ●
         ブラックリストを hosts 形式にする
       ●
         新しい hosts を作る
実行     ●
         新しい host を上書きする
確認     ●
         以前の hosts との差分を取る
後処理    ●
         古いバックアップを削除する

      大体この 4 つに分割されます。
何で組むか!?
誰もがお世話になるツール、make です!

●
  良しなに並列処理してくれる。
●
  負荷が高い時には単列処理に自動で変更する。
●
  エラーがあれば、自動的にストップ。




    まさに root で使うのに最高のツールです。
Makefile の作り方
作るもの : 作る材料
 作り方
または
作るもの : 事前にしなければいけないこと
 作り方




        とても簡単です。
変数の設定                           【ワンポイント】
                                GNU make だと := で展開後
# Settings       -   設定         の変数が代入できて便利だよ。
SHELL            =   /bin/bash
MAKEFLAGS        =   -j 4 -l 4 -s
TMP              =   /tmp

HOSTS            =   /etc/hosts
HOSTS_LAN        =   /etc/hosts.lan
BLACKLIST_URL    =   http://someonewhocares.org/hosts/
GENERATION       =   3

TODAY            := $(shell date +%Y%m%d%H%M%S)




         -j が同時処理数、-l が負荷の設定
Makefile の骨子
all:        Prepare 
            Execute 
            Check   
            Clean

# Prepare   - 準備
Prepare:    backup_hosts              
            get_blacklist             
            format_blacklist_to_hosts 
            make_new_hosts

# Execute   - 実行
Execute:    overwrite_hosts

# Check     - チェック
Check:      diff_hosts

# Clean     - 後処理
Clean:      remove_older_hosts
backup_hosts:
backup_hosts:

  cp ${HOSTS} ${HOSTS}.${TODAY}



get_blacklist:
get_blacklist:

  wget -q -o /dev/null ${BLACKLIST_URL} 
     -O ${TMP}/get_blacklist
format_blacklist_to_hosts:
format_blacklist_to_hosts:   get_blacklist

  awk '$$0 ~ /^127/ {print $$0}' ${TMP}/get_blacklist 
     > ${TMP}/format_blacklist_to_hosts
                                        【ワンポイント】


make_new_hosts:
                                        Makefile で $ は $$ と記載
                                        する。



make_new_hosts:              format_blacklist_to_hosts

  cat ${HOSTS_LAN} ${TMP}/format_blacklist_to_hosts 
     > ${TMP}/make_new_hosts
overwrite_hosts:
overwrite_hosts:            make_new_hosts

  rm ${HOSTS}
  mv ${TMP}/make_new_hosts ${HOSTS}
                                       【ワンポイント】


diff_hosts:
                                       「実行」は可能な限り一瞬で完
                                       了する方法を使おう。



diff_hosts:                 make_new_hosts

  diff -u ${HOSTS}.${TODAY} ${TMP}/make_new_hosts
remove_older_hosts:
remove_older_hosts:         backup_hosts

  ls -1 ${HOSTS}.*               |   
  egrep '${HOSTS}.[0-9]{14}$$'   |   
  sort -r                        |      【ワンポイント】
  awk 'NR > ${GENERATION}'       |      grep よりも egrep を使うと
  xargs rm -f                            便利だよ。リテラルなら
                                         fgrep が便利だよ。




        うまく分割して、小さくまとめる。
本当に高速化されているの?
全 7 項目に sleep 1 を割り当てて実行してみる。

$ time make -f Makefile
0.02s user 0.03s system 0% cpu 7.061 total

$ time make -j 4 -f Makefile
0.02s user 0.03s system 1% cpu 4.040 total




           ちゃんと並列処理されている。
もうひとつの並列処理コマンド
xargs も並列処理できるよ。

$ time seq 5 | xargs -n 1 sleep
0.00s user 0.00s system 0% cpu 15.111 total

$ time seq 5 | xargs -P 5 -n 1 sleep
0.00s user 0.01s system 0% cpu 5.007 total




           ちゃんと並列処理されている。
まとめ
やることを最初に抜き出して、「準備」「実行」
「確認」「後処理」のどれに当てはまるかを考えよ
う。
順序を少し考えるだけで、make の世界では並列処
理できちゃいます。




       「実行」は短く。
まとめ
プログラミング言語単独で並列処理をしようとする
と大変ですが、普通に処理するだけで並列処理する
仕組みは準備されているのです。




      早速、帰ったら復習だぁ!

お手軽並列処理