USP MAGAZINE

いろんな音を聴いて、世界が広がる

プロフェッショナル達の素顔

神田京子さんに訊く、
真打の話芸

ア！
ニケージエンジニ
これであなたもユ

ユニケージ開発手法教育講座
新連載「ユニケージ開発手法教育講座」は、ユニケージ開発手法におけるデータ管理の方法や、オリジナルコマンドの開発プロジェクトの進め方まで、ユニケージエンジニアとしてのトータルスキルを習得できます。

http://www.usp-lab.com/LECTURE/CGI/LECTURE.CGI
ジ
ユニケー
術講座
基礎技

も充実中！
続々と新講座K1

コマンド学習編

K2

シェルスクリプト学習編（帳票・バッチ処理）

K3

シェルスクリプト学習編（ウェブアプリケーション処理）

K4

ユニケージアーキテクチャ編

K5

ユニケージ開発環境セットアップ編

K6

システム運用・管理編

K7

プロジェクトマネジメント・人材育成編

KSQL

SQL エンジニアのためのユニケージ活用編

KSTAT

ユニケージにおける統計コマンド編

UNIX 初心者のための講座などもご用意しています。
技術の草原で百獣の王を目指す
エンジニアたちの新感覚トークライブ！

http://techlion.jp/

上記のサービス内容は 2014 年 5 月現在のものです。
最新の情報は弊社ホームページにてご確認ください。

ISBN 978-4-9048-0708-8
C3455 ￥500

USP 研究所
定価（本体 500 円＋税）

2014 June vol.14

使用方法などをハンズオン形式で具体的に学べる講座です。UNIX の基礎からユニケージ開発手法による

法林浩之のFIGHTING
TALKS
人間とコンピュータ
の可能性
ユニケージ
エンジニアの作法

2014Vol.
14
6
e
Jun
¥500

2014 June vol.14

C o n t e n t s
04

新連載 プロフェッショナル達の素顔

講談師 神田京子さんに訊く、

真打の話芸
08

漢のUNIX 第11 回

42 「シェル芸」に効く

AWK 処方箋 第3 回

後藤大地

13 シェル芸勉強会後追い企画

Haskell でやってはいかんのか？第 3 回

斉藤博文

46 教えて先輩♡

サーバー運用お助けTips
第2回

上田隆一

18

ユニケージ開発手法
コードレビュー 第 3 回

濱田康貴

50

大内智明

23

中小企業
手作り IT 化奮戦記 第 11 回

太田智美

52

スズラボ通信 第6 回

56

人間とコンピュータの可能性 第 14 回

大岩元

32

新連載

法林浩之の FIGHTING TALKS

34 組織文化を変える汗と涙の物語

アジャイル改善塾 第 2 回

36

縁の木、育てよう 第 2 回
白羽玲子

38

りゅうちの工作員日記 第 3 回
りゅうちてつや

データモデリング 第 4 回
ユニケージエンジニアの作法
第 10 回

すずきひろのぶ30

未来に活きる！ 現場で使える！

熊野憲辰

菅雄一

26

今月のeXtreme Engineer

第3弾

松浦智之

60

IPv6新時代を体感しよう！第 2 回
波田野裕一

65 幸せを考えよう シェル魔人／編集後記

シェ ル 芸 勉 強 会 後 追 い 企 画

第3回

Haskellでやってはいかんのか？

written by

産業技術大学院
・USP 研究所・USP 友の会 1

上田隆一

USP友の会のシェル芸勉強会 2 は、日々、他の言語からの他流試合に晒されているのである3 。そこで上田は、Haskellで自ら他流試合を行い、さらにシェル芸勉強会をいじめる自傷行為に手を染めるのであった。

事前準備として、次のように cabal というツール

1

はじめに

で split というパッケージをインストールしておきます。root 権限でやりましょう。

皆さん、酒飲んだくれてますか？ 富山の生んだブラッ
クエンジェル 4 上田です。

2

今回の問題 :
シェル芸勉強会第 1 回 2 問目……と、挨拶の後、別に面白いことも思い浮かばなかったのでさっさと本題に行きます。 今日からは第3 回にしてやっと 2 問目です。5/etc/passwd から、次を調べてください。
「 ロ グ イ ン シ ェ ル が bash の ユ ー ザ ー と sh の ユ ー
ザー、どっちが多い？」
たぶん私がこんな問題を出されたら、解答はこうです。
知るかボケ。……すんません（大学受験で出題された 400 字作文でこんな解答をして 浪人の遠因となった過去が）。真面目にやります。やりません。いや、やりますやります。

リスト 1
1 $ sudo cabal install split

cabal がインストールされていない場合は、第 1 回
でもやりましたが、次のようにインストールします。
リスト 2：ubuntu の場合
1 ueda@ubuntu:~$ sudo apt-get install haskell-pla
tform

リスト 3：Mac の場合
1 uedamac:~ ueda$ brew install haskell-platform

また、入力する /etc/passwd は Linux のものを想定しています。6

3

手始め : /etc/password の最後のフィールドを取得

1. 順に助教、アドバイザリーフェロー、会長
2. シェルのワンライナー勉強会
3. Ruby、Perl、PowerShell 等々。
4. 略すと富山ブラック
5. 遅い。

13

まず /etc/passwd から、集計に必要な部分だけ取得することにしましょう。シェル芸ならリスト 4 のよ
うな感じですね。
リスト 4：シェル芸でシェルのリストを作る
1 $ awk -F: '{print $NF}' /etc/passwd | head
2 /bin/bash
3 /bin/sh
4 /bin/sh
5 /bin/sh
6 ...

さて、対応する Haskell のコードはリスト 5 のよ
うになります。
リスト 5：q1_2_1.hs
1 $ cat q1_2_1.hs
2 import Data.List.Split
3
4 main = getContents >>= putStr . main'
5
6 main' :: String -> String
7 main' cs = unlines $ map getShell (lines cs)
8
9 getShell :: String -> String
10 getShell ln = last $ splitOn ":" ln関数は三つです。4 行目の main 関数は前回の問題でも出てきましたが、標準入力から字を読み込んで標準出力に加工した字を出す関数です。
6、7 行目の関数の説明はすっ飛ばして先に 9、10
行目をやっつけましょう。この関数は、/etc/passwdの一行を入力に受け付けます。受け付ける文字列は、
例えば
リスト 6

/ :? for help3（略）4 Prelude> let getShell ln = last $ splitOn ":" ln5
6 <interactive>:2:26:
7
Not in scope: `splitOn'
8
Perhaps you meant `splitAt' (imported from
Prelude)……なんか怒られてしまいました。 ちゃんと読むと 7「splitOn なんて関数ねえぞ！」と言っています。
これを解消する鍵はリスト 5、q1_2_1.hs のコードの 1 行目にあります。「import Data.List.Split」とありますが、
これは Data.List.Split という「モジュール」をインポート、
つまり使うという意味になります。
先ほど cabal でインストールしたのがこのモジュールに対応するパッケージです。中身は関数だらけです。
さて、これを知った上でもう一度 ghci でリスト 8のように試してみましょう。
リスト 8：適切なモジュールを import すると怒られない
1 Prelude> import Data.List.Split
2 Prelude Data.List.Split> let getShell ln = last
$ splitOn ":" ln
3 Loading package split-0.2.2 ... linking ... done.
4 Prelude Data.List.Split> getShell "aaa:bbb:ccc"
5 "ccc"

うまくいきました。
getShell の中身について説明すると、splitOn が、指定した文字列で文字列を切ってリスト化する関数です。

1 ueda:x:1000:1000:Ryuichi Ueda,,,:/home/ueda:/bin/bashのようなもので、この関数は、コロン区切りの最後のデータ /bin/bash を返します。ちょっと ghci でやっ

リスト 9
1 Prelude Data.List.Split> splitOn "aho" "thisaho
thataho"
2 ["this","that",""]てみましょう。リスト 7 のようになります。
リスト 7：関数が無いと叱られる
1 $ ghci
2 GHCi, version 7.4.1: http://www.haskell.org/ghc

last は、リストの最後の要素を返します。
リスト 101 Prelude Data.List.Split> last [1,2,3]

6. Mac でやってもよいのですが、なーんか /etc/passwd がぐちゃぐちゃでよく分からないんですよね……。
7. ちゃんと読みましょう。

14 USP MAGAZINE 2014 June

Haskellでやってはいかんのか？
2 3

1. 関数を新設して undefined で型チェック

では、6、7 行目の説明を。6、7 行目は、標準入の q1_2_1.hs は map getShell (lines cs) の 出 力

力から読み込まれた字を行ごとに分割してリストにしを unlines してそのまま出力していましたが、このて（lines cs の部分）、map で各行に getShell を適用

unlines に入力する前にシェルの種類を数える関数をして、map の返した文字列のリストを unlines で改行挟めばよいことになります。まず、この考えをそのまを入れてリストをくっつけて返しています。

まコードにします。リスト 13 のように書きました。

では、今度は数える部分を書きましょう。先ほど

これも ghci で試せばよいですね。リスト 11 のよ
うにやってみましょう。便利ですね〜。ghci で改行を指定するときは、\n と書いておけば大丈夫です。
リスト 11：ghci で main' を試す
1 Prelude Data.List.Split> let cs = "aa:bb\ncc:dd"
2 Prelude Data.List.Split> lines cs
3 ["aa:bb","cc:dd"]
4 Prelude Data.List.Split> map getShell (lines cs)
5 ["bb","dd"]
6 Prelude Data.List.Split> unlines $ map getShell(lines cs)
7 "bb\ndd\n"

リスト 13： q1_2_2.hs
1 $ cat q1_2_2.hs
2 import Data.List.Split
3
4 main = getContents >>= putStr . main'
5
6 main' :: String -> String
7 main' cs = unlines $ shellCount $ map getShell(lines cs)
8
9 getShell :: String -> String
10 getShell ln = last $ splitOn ":" ln
1112 shellCount :: [String] -> [String]
13 shellCount = undefined

7 行目の unlines の後ろ 8 に shellCount という関このような、関数を組み合わせるプロセスはシェル

数をはさんで、shellCount という関数を 12、13 行

芸にも通じるところがあります。入出力だけ考えると目で定義しています。……といっても、13 行目にいう点で、関数型言語とシェル芸は通じるところがあundefined とあるように、まだ定義していません。

ります。

何でこんなことをするかというと、コンパイラにか

q1_2_1.hs をコンパイルしてリスト 12 のように出力を見ておきましょう。
リスト 12： q1_2_1.hs の使用
1 ueda@remote:~/GIT/USPMAG/SRC$ cat /etc/passwd |./q1_2_1
2 /bin/bash
3 /bin/sh
4 /bin/sh
5 /bin/sh
6 /bin/sync
7 /bin/sh
8 ...

けるためで、undefined と書いておくと
リスト 14
1 ueda@remote:~/GIT/USPMAG/SRC$ ghc q1_2_2.hs
2 [1 of 1] Compiling Main
( q1_2_2.hs, q1_2_2.o )3 Linking q1_2_2 ...

というように通ります。当然実行時にエラーが出ます が。 た だ、 こ う や っ て コ ン パ イ ラ に 通 す と 型 をチェックすることができます。そのため、わざわざ
undefined と書いてコンパイルしてみたのでした。
2. shellCount を実装（前半）4では、shellCount を書いたものを示します。と言さて、数えましょう

いたいところなのですが、思ってたよりややこしかったので、途中までのコードをリスト 15 に示します。

8. 処理的には手前

15

リスト 15： q1_2_3.hs
1 ueda@remote:~/GIT/USPMAG/SRC$ cat q1_2_3.hs
2 import Data.List
3 import Data.List.Split
45 main = getContents >>= putStr . main'
6
7 main' :: String -> String
8 main' cs = unlines $ shellCount $ map getShell (lines cs)
9
10 getShell :: String -> String
11 getShell ln = last $ splitOn ":" ln
12
13 shellCount :: [String] -> [String]
14 shellCount shs = map f $ shellCount' [ (1,s) | s <- (sort shs) ]15
where f (n,str) = unwords [show n,str]
16
17 shellCount' :: [(Int,String)] -> [(Int,String)]
18 shellCount' shs = shs

このコードをコンパイルして実行するとリスト 16のようになります。
リスト 16： q1_2_3.hs のコンパイル
1 ueda@remote:~/GIT/USPMAG/SRC$ ghc q1_2_3.hs
2 [1 of 1] Compiling Main
( q1_2_3.hs, q1_2_3.o )3 Linking q1_2_3 ...
4 ueda@remote:~/GIT/USPMAG/SRC$ cat /etc/passwd |./q1_2_3
5 1 /bin/bash
6 1 /bin/bash
7 1 /bin/false
8 1 /bin/false
9 1 /bin/false
10 1 /bin/false
11 1 /bin/sh
12 ...

4 /bin/sh 17
5 /bin/sync 1
6 /usr/sbin/nologin 1

さて、q1_2_3.hs のコードを読んでいきます。まず、
17、18 行目の shellCount' は、今のところ入力をそのまま出力しています。この関数の実装は後回しにします。同じ型のものを返す関数を仮に書くときはundefined よりもこのように同じものを返しておいた方がデバッグに便利です。17 行目にあるように、この関数の型はshellCount' :: [(Int,String)] -> [(Int,String)]

つまり、シェルのパスに個数をくっつけたデータにです。(a,b)（ここでは a,b はそれぞれ Int と String）

なりました。シェルの名前はソート済みですので、あというものがありますが、これは「タプル」というもとは例えば Open usp Tukubai を使ってリスト 17

ので、二つの型の値を組み合わせるときに使います。

のようにやれば答えが出てきてしまうのですが 9、もですのでこの関数の型は「Int と String のタプルのリ

うちょっと Haskell で辛抱しましょう……。

ストを入出力する」ということになります。

リスト 17： q1_2_3 から Tukubai を使って答えを出す
1 ueda@remote:~/GIT/USPMAG/SRC$ cat /etc/passwd |./q1_2_3 | self 2 1 | sm2 1 1 2 2
2 /bin/bash 2
3 /bin/false 4

9. ああ……答えを書いてしまった……。

16 USP MAGAZINE 2014 June

んで、今回作ったメインのものは 13 〜 15 行目のshellCount です。ここには新しい書き方が二つも！
ま ず、15 行 目 の where で す が、where と 書 く と、関数の中で関数を定義できます。ここで定義しているのは関数 f で、こいつは何をやっているかというと、

Haskellでやってはいかんのか？
数字（Int）と文字列（String）のタプルを入力にもらって、数字を文字列化し、文字列とくっつけて出力して

5

おわりに

います。ghci で等価なコードを試してみましょう。
リスト 18
1 Prelude> [show 5,"abcde"] <- 5 がf の引数のn, "abcde" がstr に相当
2 ["5","abcde"]
3 Prelude> unwords [show 5,"abcde"]
4 "5 abcde"

今回はシェル芸勉強会第 1 回の 2 問目を扱いました。本編ではあまり言及しませんでしたが、今回は問題を関数に分けていくプロセスが随所で見られました。Haskell のコードを書くときは、このように頭を整理してどこで関数を分けることができるのか、探りながら書いていくことになります。実はこれ、どんな次に [ と ] で囲まれた部分ですが、これはリスト

言語でも通用する発想方法ですので、何の言語を使内包というものです。これもクドクド説明するより例

うにせよ、よいトレーニングになるかと。つまりはで示した方がいいですね。例えば下の例だと、リスト

Haskell やれということで、今回を締めさせていただ[1,2,3] から一つずつ要素を x に結びつけて、それにきます。

一つずつ 2 を足してリストにします。
リスト 191 Prelude> [ x+2 | x <- [1,2,3] ]2 [3,4,5]

次回は続きからということで、まーた途中になっち
まいましたが、来月まで辛抱強くお待ちいただければ……と。

実は、次の map を使った例と等価です。
リスト 201 Prelude> map (+2) [1,2,3]
2 [3,4,5]

んで、q1_2_3.hs のコードでは、タプルを作るためにリスト内包を使っています。具体例を下に示します。
例の中で sort も使ってみます。
リスト 21
1 Prelude> import Data.List<- sort を使うためにimport2 Prelude Data.List> [ (1,s) | s <- (sort ["bbb","aaa","ccc"] ) ]3 [(1,"aaa"),(1,"bbb"),(1,"ccc")]

さあ、最後に shellCount' を実装します。今のところタプルの数字、つまり個数はすべて「1」で出力していますが、これを同じシェルでまとめていきます。
さて次を……というところですが、紙面がもうございません。
今月はこれでお開きにしたいと思います。

● お知らせ：コード募集
本稿で出た問題の Haskell のコードを、名前あるいはハンドルネームと共に送ってください。 短いもの、あるいは変態的なものをお願いいたします。
email: mag@usp-lab.com

17

Tips

教えて先輩♡

サーバー運用お助け第2回

written by 濱田 康貴

みなさまこんにちは。(っ´∀｀)っ ゃー こと@nullpopopoでございます。

内地の梅雨は毎年のことながらゲンナリするものですが、この時期の札幌は暑くもなく寒くもなく風が爽やかな季節です。昼休みにはよく1本道を自転車でスイスイ走り、

午後の仕事に向けて気分をリフレッシュしたことを思い出します。

そんな1本道のように一気通貫一撃必殺で仕事をこなすコマンドラインの技がありまして、人はこれを「ワンライナー（一行野郎）」と呼びます。

今回はワンライナーを駆使して仕事を素早く楽にこなす術をご紹介しようと思います。
" ワンライナーとは、ある処理を行うためにプログラリックする方法とワンライナーで、同じ目的の作業を比ムを書かず（書くまでもなく）、コマンドラインを 1 行

較してみます。ここでは、CentOS 6.5 のサーバー環境に並べて実行する。"

を想定しています。

これだけでは何のことやら？と思われるでしょう。最近では、ワンライナーよりも「シェル芸」という言葉に◆ 1. GUI でぽちぽち編

馴染みを持たれている方もいらっしゃるかと思います

Gnome のメニューから「アプリケーション」を開が、シェル芸の創始者、USP 友の会会長 上田さんの言き、「システムツール」から「ディスク使用量の解析」

葉を借りてみましょう。

を起動。「ファイルシステムの解析」ボタンをクリッ" シェル芸とはマウスも使わず、プログラムも書かず、クしてから、
使用量のゲージが多い順にクリックする。

GUI ツールを立ち上げる間もなく、あらゆる調査・計算・

その後、フォルダを開いて容量の順に表示をソート

ファイル処理をコマンド入力一撃で終わらす。"

ワンライナーでできること
ワンライナーやシェル芸の説明で、どんなことができるのかが少しイメージしやすくなったかと思います。コ
マンドラインに苦手意識を持たれている方は、「マウス
でぽちぽちクリックしたほうが早いじゃん」と思われるかも知れませんが、例えば、「ある Linux サーバーで一番容量を消費しているファイルがあるディレクトリを探し、容量の大きいファイルのトップ 10 を見せてくれ」と上司から依頼されたとしましょう。GUI でぽちぽちク

46 USP MAGAZINE 2014 June

してスクリーンショットを撮るかファイル名をテキス
トにコピーしてメールで上司に報告する。
【図 1】「ディスク使用量の解析」画面

教えて先輩♡【図 2】フォルダにソートして表示する

サーバー運用お助け

tools」「gtk2-engines」「libasyncns」「libbonobo」「libbonoboui」「libcanberra」「libcanberra-gtk2」「libglade2」「libgnome」「libgnomecanvas」「libgtop2」「libogg」「libsndfile」「libtdb」「libvorbis」「pulseaudio-libs」「rarian」「rarian-compat」「sound-theme-freedesktop」「system-gnometheme」「system-icon-theme」「xml-common」がインストールされていないとなりません。

※ 前提条件として「gnome-utils」パッケージがインストールされていること

自宅の PC ならまだしも、サーバーマシンにこれだ
け多くのパッケージをインストールするということ◆ 2. ワンライナー編
ターミナルを開き、リスト 1 のワンライナーを実は、yum などのパッケージ管理を使うとしてもアッ
プデートの妥当性を考えなければなりません。そうす

行する。

ると、1 つのサーバーマシンにインストールするパッ▶リスト 1

ケージの数は少なければ少ないほど運用が楽になりま[root@localhost ~]# cd / ; while :; do TARG=$(du sk $(pwd | sed -e 's/^\/$//g')/* 2>/dev/null|sort-n|tail -n 1|awk '{print $NF}') ; [ -d $TARG ] &&cd $TARG || [ $(pwd) = $(cd -) ] && ls -lk | sort-n | tail -n 11; [ ! 0 = $(echo $?) ] && break ; p
wd ; done | tac | head -n 12

す。
さらに、毎日同じ作業を繰り返すとなると、GUI 操
作を行うために人が張り付かなければなりません。一方、ワンライナーであれば、テキストのコピペで再実行が容易で、かつ何度繰り返しても同じ条件のアウト

これを実行するだけ（USP MAGAZINE Vol.12 拙

プットができます。自動化だって、cron から起動し

著「教えて先輩♡ サーバー運用お助け Tips」より引てメールで飛ばすようにすればそれでおしまいです。

用および改変）。実行結果例は図 3 参照。詳細は " お

他人に同じ仕事をしてもらうのだって、GUI を人にクまけの解説 " で説明いたします。

リックしてもらうにはテキストの説明だけでは何かと【図 3】

不安です。さりとて図解入りの手順書を作る作業に時間をかけたくないですよね？
しかし、ワンライナーであれば「これコピペして実行して結果をメールにコピペしてちょうだい」と伝えるだけです。後ろ向きな仕事やそれに伴うコミュニ
ケーションに時間をかけるくらいなら、仕事はさっさと終わらせてコーヒーでも飲みながら同僚と雑談して※ 前提条件として「gawk」「coreutils」「sed」パッケージがインストールされていることGUI でぽちぽちの方が楽で、しかも前提条件が緩そ う で す が、 そ も そ も「gawk」「coreutils」「sed」

いたほうがよっぽど職場によい空気をもたらすと思いませんか？

ワンライナーの書き方

パッケージは GUI の有無に関係なくどんなマシンにコマンドを 1 行で繋げて実行するのがワンライナー

もインストールされています。仮に、サーバーマシンというのはこれまでの例で理解できたかと思います。

で GUI を使う目的で「gnome-utils」をインストー

ではどうやって 1 行にするのか？についてもう少しルするには少なくとも「avahi-glib」「dmz-cursor-

パターンを整理したいと思います。

themes」「flac」「gnome-icon-theme」「gnome-（1）複数のコマンドをとにかく 1 行で実行する

panel-libs」「gnome-themes」「gnome-utils-

例えば、サーバーのロードアベレージとメモリ使用

libs」「gnome-vfs2」「gstreamer」「gstreamer-

量、ディスク使用率を見たい場合、単純にコマンドを47

「;」で区切って 1 行で実行することができます。

いることを表示するコマンドですが、ヘッダには、現▶リスト 2

在の時刻、システムが稼働している期間、現在ログイ[hamada@localhost ~]$ w ; free -m ; df -h
13:19:50 up 1 day, 18:21, 2 users, load average: 0.07, 0.06, 0.02
USER
TTY
FROM
LOGIN@ IDLE
JCPU PCPU WHAT
hamada tty1
:0
Thu18 42:21m
30:24 0.02s pam: gdm-password
hamada pts/0
:0.0
13:11
0.00s
0.06s 0.00s w
total
used
free
share
d
buffers
cached
Mem:
7779
3254
4525
0
192
1198
-/+ buffers/cache:
1862
5916
Swap:
199
0
199
Filesystem
Size Used Avail Use% Mounted on/dev/sda3
117G 41G 71G 37% /tmpfs
3.8G 9.6M 3.8G 1% /dev/shm/dev/sda1
194M 122M 63M 67% /boot

しかし、これだけでは見づらいので、各項目の表題をつけたり空行をつけてみたくなるでしょう。次の「（2）コマンドの出力をパイプで区切る」で、もう少し見やすく整形してみることにします。
（2）コマンドの出力をパイプで区切る
コマンドの出力をパイプで区切ることにより、前に実行したコマンドの出力結果を次のコマンドに食わせンしているユーザーの数、過去 1、5、15 分でのシステムの平均負荷が順に表示されるので、ロードアベ
レージだけを表示させるよう grep と awk で整形しています（※ 1）。grep で「load average」が表示されている行を捕まえ、awk コマンドで 8 〜 12 列
目を抜き出しています。また、すべてのコマンドを実行する前に、echo コマンドでタイトルをつけたり、
echo の後に引数を与えずコマンド実行後に空行をつけたりしています。
こうしてパイプで区切れるということは、1 回 1 回
サーバーにログインせずとも毎日決まった時間にメー
ルでコマンド出力結果を受け取れるということです。
しかし、複数コマンドをまとめて 1 通のメールとして送信するには少し工夫が必要です。
▶リスト 4[hamada@localhost ~]$ for A in :; do echo "ロードアベレージ"; w | grep "load average" | awk '{print$8,$9,$10,$11,$12}'; echo ; echo "メモリ使用量";
free -m ; echo; echo "ディスク使用率" ; df -h ; done | mail -s "$(date) $(uname -n) SYSTEM STATUS" hamada@localhost

先ほどのコマンドを、bash の for 文で囲って 1 つることができます。

の塊にし、これをパイプラインで mail コマンドに▶リスト 3

渡してあげています。for 文は「for A in 1 2 3; do[hamada@localhost ~]$ echo "ロードアベレージ" ; w| grep "load average" | awk '{print $8,$9,$10,$11,$12}' ; echo ; echo "メモリ使用量" ; free -m ; echo ; echo "ディスク使用率" ; df -h
ロードアベレージ
load average: 0.02, 0.03, 0.00

入した値のぶんだけ実行する使い方が一般的かと思いますが、ここではちょっとだけトリッキーに「:（true）」
コマンドを代入しています。こうすることで、for 文の do から done までに囲まれたコマンドを 1 回だけループ実行することができます。あとはこのワンライメモリ使用量total
dbuffers
cached
Mem:
7779
0
192
1197
-/+ buffers/cache:
Swap:
199
ディスク使用率
Filesystem/dev/sda3
tmpfs/dev/sda1

echo $A; done」などのように、愚直に変数 A に代

used

free

3239

4539

1849
0

5930
199

share

ナーを cron に登録してあげれば、わざわざターミナ
ルにログインしなくてもサーバーの状態を簡単に見ることができるでしょう。
（3）前に実行したコマンドの成功と失敗によって処理を使い分ける

Size
117G
3.8G
194M

Used Avail Use% Mounted on
41G 71G 37% /9.6M 3.8G 1% /dev/shm
122M 63M 67% /bootw コマンドはログインしている人やその人がやって48 USP MAGAZINE 2014 June

ここまでのワンライナーでは、コマンドの区切りが2 つ登場しました。
「:（true コマンド）」と「|（パイプライン）」です。しかし、条件によって処理を使い分けたいこともあるでしょう。次の例では、ロードアベ
レージが 1 を超えたときとそうでないときでメッセー

教えて先輩♡ジを変えたい場合の使い分けを取り上げてみましょう。直近のコマンドが正常終了であれば、「&&」の後サーバー運用お助け

正常終了したときに実行したいコマンド || test コ
マンドが異常終了したときに実行したいコマンドに続くコマンドを実行します。直近のコマンドが異常終了であれば、「||」の後に続くコマンドを実行します。
▶リスト 5[hamada@localhost ~]$ Threshold=4 ; NUM=$(echo "$(w | grep "load average" | awk '{print $10}' | sed-e s/,//g)*100" | bc) ; [ $(expr ${Threshold} \* 100) -gt $(echo $NUM | awk 'BEGIN {FS="."} {print $1}') ] && echo "ロードアベレージは${Threshold}より小さいので正常域です" || echo "ロードアベレージは${Threshold}を超えました"

サーバーのロードアベレージが、ある閾値を超えたかどうかによって出力するメッセージを変えてみました。今回の例では閾値を「Threshold」という変数で指定します。次に、直近のロードアベレージを w コ

1 つ補足しますと、「&&」や「||」の前は必ず test
コマンドでなければいけない、というわけではなく、直前に実行したコマンドが正常終了したかどうかで処理を分けたい場合に使うと便利です。例えばこういう使い方もできます。
▶リスト 6[hamada@localhost ~]$ touch hoge && echo "hogeファ
イルを生成できました" || echo "hogeファイルの生成に失敗しました。ディレクトリのパーミッションを確認
してください"おまけの解説マンドから抜き出すのですが、test コマンドの中でワンライナー編のリスト 1 を詳しく解説します。

閾値より小さいかどうかの比較をするのに小数点の計/ ディレクトリから順に、du コマンドで一番容量算ができないので、「NUM」変数で 100 をかけてあを消費しているディレクトリへ cd していきます。なげます。同じく、test コマンドの中で「Threshold」

ので最初に「cd /」しています。while のループの中変数の値も 100 倍にしてあげています。そして、ロー身ですが、du コマンドでカレントディレクトリ直下

ドアベレージが閾値より小さければ正常終了なので、で一番容量を食っているファイルやディレクトリを

このワンライナーを実行した後は「ロードアベレー「TARG」変数に入れています。そして、これがディジは 4 より小さいので正常域です」と表示されます。

レクトリだったら cd して、ループの先頭に戻ります。

何らかの理由で CPU 処理の待ちが多いと、「ロード最終的に変数 TARG がファイルになるまでこれを繰

アベレージは 4 を超えました」と表示されます。

り返し、今いるディレクトリと直前にいたディレクト

test コマンドのオプションは数値の比較のほか、リが同じになったところで ls の結果をキロバイト単ファイルの有無や文字列比較も行うことができますの位でソートして表示し、現在のディレクトリを表示しで、是非使いこなしてみてください。あまり条件を複てループを抜けます。あとは逆順にならべて head で雑にしすぎても大変かと思いますが、エラーハンドリ

整形しておしまいです。

ングをきちんと考えてワンライナーを実行したりプロ

いかがでしたでしょうか。ワンライナーを使うメ

グラムを書いたりするクセをつけておけば、何かエ

リット、そして何ができるのかがイメージできると、ラーがおきたときの対処を早めることに繋がります。

明日からの仕事がよりよいものになるでしょう。

ワンライナーの書き方まとめ※ 1 jman より引用

http://linuxjm.sourceforge.jp/html/procps/man1/w.1.html

それでは、ここまでのまとめを見てみましょう。
● コマンドの単純な区切りは「;」で行う
command1 ; command2 ; ...
●コマンド出力結果を次のコマンドに食わせる
command1 | command2 | ...
● test コマンドを使い、条件分岐を行う[ 条件 1 オプション 条件 2 ] && test コマンドが49

未来に活きる！ 現場で使える！

データモデリング第 4 回 イベント系のモデリングwritten by 熊野憲辰
第3回より具体的なデータモデリングについて解説している。前回は「マスタ系」のモデルを考察した。

今回は「イベント系」のモデルについて述べる。イベントとは、企業活動における出来事そのものを指し示している。

順序と多重度モデリングの観点から見た時、企業活動の中における「出来事」とは何を表わす言葉だろうか。例を挙げると、受注した、仕入れた、出荷した、入荷した、などがここのモデル事例を解説していこう。
●パターン 1
先行・後続イベントが 1:1 で起きるケース
受注 1 件に対して、出荷というイベントが 1 対 1で発生するパターンになる（図 1）。

でいう「出来事」に該当する。出来事の発生は「伝票」

受注に関する詳細な属性は、受注エンティティにという体裁で認識することができる。また前回触れたよ保持されている。出荷エンティティ側には、「出荷番

うに、イベントには必ず日付が属性として帰属する。

号」「出荷日付」「配送業者コード」が主となる属性がここで一般的な伝票というものをイメージしてほしい。

ある。このモデルのポイントは、出荷エンティティに伝票のヘッダーには日付や取引先などの情報が、明細に「受注番号」を保持している、ということだ。すなわ

は商品や数量、金額が記載されている。つまり「伝票にち受注番号が、「どの取引先からの受注なのか」といおける明細」こそが、最も粒度の小さいイベントを表わ

う情報、または商品、数量、単価などの属性を代表ししていることを理解できる。

ている。しかし、こうなっていないモデルをよく見か

この伝票明細を素直に記録していくことがイベント系のモデルにおいて重要になる。
ご存知のようにデータベースは、集計処理が大得意である。最も細かな明細単位で、企業活動の出来事を漏れける。端的なのは出荷エンティティ側に取引先コード
や商品コード、数量、単価などを引きずっているケースだ。これは冗長であり正規化されていないモデルといえる。

なく記録していけば、それを集計したり加工したりとい

受注エンティティに帰属する属性、出荷エンティ

う処理は単純なアルゴリズムで実現できる。伝票明細レ

ティに帰属する属性を正確に区別してモデル化するよ

ベルでイベントを漏れなく素直に記録できていれば、後うにしよう。

はなんでもござれ、というわけだ。

図 1：多重度 1:1 のモデル

ただし、この「出来事を漏れなく素直に記録する」という作業には、ややコツが要る。出来事には「先行」と「後受注続」があるからだ。ある出来事が発生した後に、次の出

受注番号来事が発生する、またはそうでなくてはならない、といった「順序」がたいへん重要である。受注という出来事の後に、出荷という出来事が起きるというのは、まさにそうした順序の一例だ。
その上で留意したい点は、出来事の先行・後続における「多重度」がモデリングを難しくする一因にあること。
受注〜出荷という先行・後続イベントを例に、いくつか
52 USP MAGAZINE 2014 June

受注日付
取引先コード
商品コード
数量
単価

出荷
1

1

出荷番号
出荷日付
配送業者コード
受注番号●パターン 2
複数の受注が 1 回の出荷となる（N:1）ケース
実務では、複数の受注をまとめてから出荷を行うこちらのパターン 2（N:1）のほうが、圧倒的に多いだろう。受注 1 件につき毎回出荷するのは効率が悪い

ンティティに保持している。
受注、出荷ともに、それぞれのエンティティに帰属す
る属性だけを保持していることを確認してもらいたい。

からだ。
この場合、モデル図は、図 2 となる。受注と出荷の関係は、N:1（図で N 側は * で記述）だから、パター●パターン 4
サブタイプ構造を持つケース

ン 1 のように出荷エンティティ側に受注番号を保持

受注と出荷の順序関係において、受注→出荷だけでさせることはできない（複数の受注番号があるため）。

なく、受注→製造→出荷のようなオーダーメイドのパだから、受注と出荷のエンティティ間に双方の対応関

ターンもある。そして、受注エンティティが、サブタ係を表にして保持する、ということを表わしている。

イプ構造として、在庫品受注とオーダーメイド受注にこの対応表で、受注からみた後続の出荷、出荷から在庫品受注は、そのまま出荷に向かう（ここでは、みた先行の受注をたどることができる。

在庫引当、梱包などのイベントは無視している）。オー

図 2：多重度 N:1 のモデル

ダーメイド受注は、受注の後、製造イベントを経て出

受注

出荷

受注番号
受注日付
取引先コード
商品コード
数量分かれるパターンを考える。

出荷番号
出荷日付
配送業者コード1単価荷となる。これをモデル化すると図 4 になる（多重度はすべて 1:1）。
図 4 では、出荷エンティティもサブタイプ構造を持つことになる。そして、在庫品出荷は、先行イベン
トの番号である受注番号を保持し、オーダーメイド出1

荷は、製造番号を保持している。

*
受注・出荷関係

ここで、キーとなる番号の付け方について補足を1する。今回のようなモデルで、受注番号の 1 桁目を、在庫品受注の場合は「1」、オーダーメイド受注の場

受注番号
出荷番号

合は「2」などとやってはいけない。あくまで一つのイベントの番号は単なる連番として設定する。この点●パターン 3についてはマスタ系でもイベント系においても例外は

1 回の受注が複数の出荷（1：N）となるケースない。

1 回の受注に対して 2 回、3 回に分けて出荷する業
務もあるだろう。ある商品を 100 個出荷するという受注に対して、60 個をまず出荷、その後 40 個を別の日に出荷した、というような事例である。

●パターン 5
「ヘッダー・明細」構造を含むケース
冒頭で触れたように、企業活動の出来事は、生成された受注伝票や出荷伝票の中のヘッダーと明細によっ

モデル図は、図 3 となる。出荷エンティティに受て記述されている。もちろん、在庫引当やピッキング

注番号を保持しているという点では、図 1 と同じでなど、一般的には伝票として記述されないイベントもある。そして、複数の出荷における出荷数量を出荷エ多々ある。
伝票の体裁は多種多様だが、企業の情報システムで

図 3：多重度 1:N のモデル扱われるデータは、ヘッダーがあり、明細行が複数存

受注
受注番号
受注日付
取引先コード
商品コード
数量
単価

出荷
1

*

出荷番号
出荷日付
配送業者コード
出荷数量
受注番号

在する場合がほとんどである。
これまでのパターンで述べてきたような単体のエンティティに、ヘッダーと明細を組み合わせたエンティ
ティが加わると、モデルの示し方に少し難しさが増す。
図 5 に、先行→後続という関係が、ヘッダー単位で推移する場合のモデルを示そう。

53図 4：サブタイプ構造を持つ先行・後続モデル

受注
出荷

受注番号
受注日付
取引先コード
商品コード

出荷番号

数量

配送業者コード
出荷区分

出荷日

単価
受注区分
受注区分

出荷区分

オーダーメイド受注

在庫品受注

オーダーメイド出荷

在庫品出荷

受注番号

受注番号

1

1

出荷番号
製造番号

出荷番号
受注番号

先行

先行

後続

後続

1

1

製造
後続

1

製造番号
製造日付
受注番号

図 5：伝票明細のエンティティを加える

受注
受注番号
受注日付
取引先コード

1

*
受注明細
受注番号
受注行番号
商品コード
数量
単価

54 USP MAGAZINE 2014 June11

図 6：ヘッダー・明細構造と多重度が追加

出荷

1

先行

出荷番号
出荷日付
配送業者コード
受注番号

受注
受注番号
取引先コード
受注日付

出荷

1

出荷番号
出荷日
託送業者コード

*

受注明細
受注行番号
商品コード
数量
単価

1

1

*

1 受注明細・出荷
受注番号
受注行番号
出荷番号

●パターン 6
明細単位で先行・後続するケース

3）多重度をモデル化するイベントの先行・後続が明確になったら、それぞれ

図 6 は、ヘッダー・明細構造において先行する受の多重度を分析してみる。本稿で挙げた事例は、受注

注明細が、後続の出荷につながるパターンのモデル図

からいきなり出荷という流れであったが、実際の物流である。この場合、異なる受注の明細をいくつか集め

業務では、在庫引当、ピッキング、梱包などのイベンてから、1 回の出荷を行う、ということを表わしておトが途中に存在する。『複数の受注を一括で在庫引当り、企業の物流システムにおいて最も一般的なモデル

するのかどうか』『ピッキングも、種まき方式なのか、であるといえる。

摘み取り方式なのか』などを考慮して多重度を慎重にこのモデルでは、複数の受注明細が 1 回の出荷に分析しなければならない。

つながるので、受注明細と出荷のエンティティ間には、
パターン 2 のように、対応関係を記述するテーブルが置かれることになる。このテーブルには、受注番号と受注行番号、出荷番号が保持されている。

イベント系モデルの作成手順

4）ヘッダー・明細構造の分析
重ねて強調したいが、最初からヘッダー・明細を考慮しないほうがわかりやすい場合が多い。大きな流れや構造を分析した後にヘッダー・明細を与えると混乱が起きにくい。

ここまで、先行・後続における各種パターンとみて

ただし、伝票や画面、帳票をベースにモデルを作成

きた。まとめとして、イベント系のモデルの作成を手し、それぞれを統合する場合には、最初からヘッダー・順に沿って解説する。

明細の構造を認識することになる。もちろん、このよ
うなボトムアップによるアプローチでモデル化するこ

1）業務のトリガーとしてのイベントを見極める
各事例では、受注を業務の先頭に置いているがそうでないことも多いだろう。例えば、見積り。見積りをとに問題はない。ただし、イベントの全体像を見失わないように先行・後続、サブタイプ構造などへの目配りは欠かせない。

行った、という事実を記録し、その後続として受注がある、というモデルだ。この場合、見積り内容と実際の受注内容は異なることも予想される。そして、受注にはつながらないことも考えられる。モデル化する時は、これらを考慮する。
見積り作業に関しては、画面からの入力は行うがエンティティとして記録せず、XML ファイルなどでシリアライズして保持するに留める、というのも実践的なアプローチのひとつである。
2）イベントの後続を考慮しサブタイプ構造を洗い出す
前回のマスタ系のモデルについての解説でも述べたが、エンティティをサブタイプ構造で立体化することは、自社業務の整理、可視化に大いに役に立つ。
特にイベント系は、先行・後続の関係が重要なので、これをベースにサブタイプに分類することが有効だ。
また、この段階ではヘッダー・明細構造を特に意識せずにスケッチすると、理解しやすい。

55

USP MAGAZINE

いろんな音を聴いて、世界が広がる

プロフェッショナル達の素顔

神田京子さんに訊く、
真打の話芸

ア！
ニケージエンジニ
これであなたもユ

ユニケージ開発手法教育講座
新連載「ユニケージ開発手法教育講座」は、ユニケージ開発手法におけるデータ管理の方法や、オリジナルコマンドの開発プロジェクトの進め方まで、ユニケージエンジニアとしてのトータルスキルを習得できます。

http://www.usp-lab.com/LECTURE/CGI/LECTURE.CGI
ジ
ユニケー
術講座
基礎技

も充実中！
続々と新講座K1

コマンド学習編

K2

シェルスクリプト学習編（帳票・バッチ処理）

K3

シェルスクリプト学習編（ウェブアプリケーション処理）

K4

ユニケージアーキテクチャ編

K5

ユニケージ開発環境セットアップ編

K6

システム運用・管理編

K7

プロジェクトマネジメント・人材育成編

KSQL

SQL エンジニアのためのユニケージ活用編

KSTAT

ユニケージにおける統計コマンド編

UNIX 初心者のための講座などもご用意しています。
技術の草原で百獣の王を目指す
エンジニアたちの新感覚トークライブ！

http://techlion.jp/

上記のサービス内容は 2014 年 5 月現在のものです。
最新の情報は弊社ホームページにてご確認ください。

ISBN 978-4-9048-0708-8
C3455 ￥500

USP 研究所
定価（本体 500 円＋税）

2014 June vol.14

使用方法などをハンズオン形式で具体的に学べる講座です。UNIX の基礎からユニケージ開発手法による

法林浩之のFIGHTING
TALKS
人間とコンピュータ
の可能性
ユニケージ
エンジニアの作法

2014Vol.
14
6
e
Jun
¥500