unix/linux:決められた時刻に処理を実行する(ワンライナー編)

unix/linuxの便利コマンドの紹介です。


テストや補正作業を行う際、決められた時刻に決められたコマンドを実行したい場合があります。
unix/linuxでは、atコマンドを使用することで、決められた時刻に決められたコマンドを自動的に実行するように登録することができます。

しかし、atコマンドを通常の使い方をする場合、対話式にコマンドを入力したりコマンドを記載したファイルを別途用意したりする必要があり、オペレータに作業を依頼したりシェルスクリプトに組み込んだりする場合に都合が悪い場合があります。
そこで、下記のようにプロセス置換(コマンドをファイルに見立てる記法)を用いることで、対話式のコマンド入力やファイルの用意をする必要がなくなります。

・20:00に/home/hoge/test.txt(空ファイル)を作成するように登録する例

#> at 20:00 -f <(touch /home/hoge/test.txt)


OSのバージョンやatコマンドの設定によっては、atコマンドを使用できない場合もあります。
その場合は、下記のようにループ処理とバックグラウンドを併用することで、atコマンドと同じようなことを実現できます。

・20:00に/home/hoge/test.txt(空ファイル)を作成するように登録する例

#> (TIME=date "+%H%M"; while[${TIME} -lt 2000]; do sleep 60; TIME=date “+%H%M”; done; touch /home/hoge/test.txt) &


いかがでしたでしょうか。

unix/linuxのコマンドを使いこなせるようになると、できる作業の幅が広がります。
今回紹介したコマンドも、使う機会が少なくないのではと思います。

これからも、便利コマンドを紹介していきたいと思います!

ウォーターフォールモデルとV字モデル

日本でシステム開発を行う場合、多くの場合は「ウォーターフォールモデル」と呼ばれるプロセスに従って開発を進めます。
ウォーターフォールモデルを知ることで、各々の工程を何のために行うのかを考えることができるようになります。
システム開発作業に参画する際は、ウォーターフォールモデルについて知っていることが望ましいです。

ウォーターフォールモデルでは、実際にプログラムを作るまでは「要件定義(基本計画)」→「外部設計(基本設計)」→「内部設計・プログラム設計(詳細設計)」→「プログラミング(製造)」といった工程を踏みます。
ユーザの要求からスタートし、段階的に詳細化しシステム化の方針を決めるといった形で、トップダウンで開発を行います。
プログラムを作り終えてからは、「単体テスト(UT)」→「結合テスト(IT)」→「システムテスト(総合テスト、ST)」→「運用テスト(UAT)」といった工程を踏みます。
バグ頻発でテスト進行が妨げられることを防ぐために、細かい箇所からテストを行い徐々に統合するという形で、ボトムアップで開発を行います。

開発工程とテスト工程は、以下のように連関しています。

プログラミングの内容は単体テスト、内部設計・プログラム設計の内容は結合テスト、外部設計の内容はシステムテスト、要件定義の内容は運用テストで検証します。
これをV字モデルと呼びます。

誤りを修正する場合、後の工程になるほど手戻り工数が増え、修正コストが増大します。
最悪なのは、リリース後に誤りが発見され、修正の必要が生じた場合です。
そのため、手戻りは原則として行わず、各々の工程を順番にこなしていくことが理想です。
(水が流れるように順番に工程をこなすことから、「ウォーター(水が)フォール(流れ落ちる)」と呼ばれるようになりました)

手戻りを防ぐためには、レビューを強化する等し、ある工程で埋め込んだ誤りはその工程の中でできる限り解消することが重要になります。
仮に後の工程で誤りが発見された場合は、その誤りについてなるべく早い段階で例外的に前工程に戻り、その誤りの修正に関わる要件・設計・実装を見直すことが重要になります。
大規模かつミッションクリティカルなシステム開発では特にこの原則を守ることが重要となります。
以下は東証のシステム更改の例で、前工程への手戻りを正式にプロセスに組み込むことで手戻り工数を削減する「フィードバック型V字モデル」が採用されました。
http://ac.nikkeibp.co.jp/cn/xdev10/pdf/10907-xdev-A-1.pdf

また、実現性が疑わしい箇所について開発開始前にプロトタイプを作成し、実現性をあらかじめ検証するという手法も使われます。
プロトタイプを作ることで、開発開始時に実現性の問題が出て手戻りが発生することを防ぐことができます。
(このような事前検証は「POC」と呼ばれることもあります)

ざっくりまとめると、先が見える場合は1つ1つの作業を確実にこなす、先が見えない場合は先回りして視界を良好にする、という姿勢がプロジェクトを円滑に進める上で重要になります。


いかがでしたでしょうか。

私も1~2年目だった頃は、手戻りのリスクを考えずに猪突猛進に作業を進めて、結局手戻りして先輩に迷惑をかけたことがあります。
若手なら先輩に迷惑をかける程度で済みますが、リーダーや管理者の立場で同じことをすればプロジェクト全体の進捗に影響してしまいます。

ウォーターフォールモデルはシステム開発のプロセスとしては基本的なものですが、基本だからこそないがしろにしてはいけないと思っています。
単純に各工程の名前と作業内容を覚えるだけでなく、その背景にある理念も含めて理解する必要があると思っています。

それではまた次回!

unix/linux:perlの複数命令を1行のコマンドで実行する(例:文字列のバイト位置走査)

perlはファイル操作や正規表現に優れているスクリプト言語であるため、コマンドライン上でperlを駆使することができれば作業の幅が広がります。
perlの-eオプションによりコマンドライン上で実行可能となり、1つ1つの命令を ; で区切ることで複数命令を記述可能となるため、これを使いこなすことでスクリプトを作らなくともperlの機能を作業に使うことができるようになります。
コマンドを予め作成して本番作業時にコピペしたい場合やオペレーターに作業を依頼する場合等、スクリプトを気軽に作れない場合も少なくないので、そのような場合に効果を発揮します。

以下は、ファイルの中から特定の文字列のバイト位置を走査する例です。
ファイルの先頭で見つかった場合は0、次のバイトで見つかった場合は1、…といった具合で値が返ります。
見つからなかった場合は-1が返ります。
(例えば、改行コード無しのファイルで特定のデータをcutで除外したい時に、除外する位置を確認するのに使えます)


いかがでしたでしょうか。
perlという言語自体は知っている方が多いと思いますが、それをコマンドラインから実行して作業を効率化できる、というのは盲点ではなかったでしょうか。

ちなみに、今回紹介しませんでしたが、perl -eには便利な追加オプションがいくつもあります。
(標準入力(インプット)を1行1行処理、改行の強制付与、等)
「perl ワンライナー」で検索すると参考になるページが出てくるので、更に複雑な操作を行いたい場合は調べてみると良いでしょう。

では、また来週!

gitとsubversionの違い

gitとsubversionの違いについて良く聞かれるので、記事にしてみました。

【git・subversionとは?】

gitもsubversionも共にバージョン管理システムであり、古典的なバージョン管理システムであるCVSからの流れを汲んでいます。
バージョン管理システムとは、ソースコード等のファイルを管理するシステムであり、過去のバージョンを保持することができるため、障害や要望が発生した時にある時点のバージョンまで遡ることが容易になります。
(バージョン管理システムを使っていれば過去のバージョンを指定して落としてくるだけで良いですが、使っていないと手動で過去バージョンのファイルをかき集めたり復元したりという作業が発生します)
gitの方が後発ですが、現在はgitの方がメジャーです(少なくとも国際的には)。

【gitとsubversionの違い】

一言で言うと、subversionは集中型バージョン管理システム、gitは分散型バージョン管理システムという違いがあります。
集中型と分散型の違いについては、下記図に表しました。

集中型管理システムでは、リポジトリ(ファイルのバージョン管理を行う書庫)はリモート環境にのみ存在します。
メンバーはリモート環境のリポジトリにアクセスし、各メンバーのローカル環境にあるファイルをコミット(新バージョンとしてファイルを保存)したり、ローカル環境へチェックアウト(特定のバージョンのファイルを取得)したりします。

一方、分散型管理システムでは、リポジトリはリモート環境のみでなく、各メンバーのローカル環境にも存在します。
メンバーは自分のローカル環境のリポジトリに対し、コミットやチェックアウトを行います。
ローカル環境でコミットしたファイルについては、適切なタイミング(テストが完了したタイミング、リリース準備を行うタイミング等)でプッシュを行い、リモート環境のリポジトリへコミットを反映させます。
また、ローカル環境のリポジトリを作る際は、リモート環境のリポジトリから特定のバージョンの情報をプルで取得します。

【分散型管理システムの利点】

利点はいくつか挙げられますが、一番本質的な利点は自分のコミットが他のメンバーへ影響を与えずに済むという点です。
集中型管理システムの場合は、コミットしたファイルは即座に他のメンバーも取得可能となるため、仮にバグを取り除き切れていないソースコード等をコミットしてしまうと他のメンバーに迷惑をかけてしまいます。
しかし、分散型管理システムであれば、自分のリポジトリでチェックしてからリモート環境のリポジトリへ反映させることができるので、他のメンバーへ迷惑をかけずに作業を進めることができ、生産性が向上します。

他には、「分散型管理システムであればローカル環境のリポジトリがバックアップとなるため障害耐性が向上する」等の利点を挙げる文献もありますが、個人的には本質的な利点だと思っていません。
(例えばバックアップの例なら、集中型管理システムでも定期的にバックアップを取得する運用体制とすれば障害耐性を向上させられます)

【gitにおけるブランチの使い方】

gitではブランチを使用することができ、コミットを複数に枝分かれさせることができますが、自分のコミットが他のメンバーへ影響を与えないという利点は、ブランチ機能と親和性があります。
gitの場合は、「機能毎に担当者を決める→各々の担当者がブランチを切る→自分が開発した機能を自分のリポジトリへコミットする→自分の環境で機能の検証を行う→検証済みのコミットをリモート環境のリポジトリへプッシュし、枝分かれしたコミットをマージする」という開発体制を取ることができます。

このように、担当者毎・機能毎でブランチを切ることができるため、機能毎にプッシュ可否を判定する、ある機能だけバージョンを戻す、といった柔軟な運用が可能になります。

なお、subversionにもブランチの機能はあるのですが、各担当者が思い思いにブランチを切るという使い方はできないので、バージョン毎(マスターバージョンとβバージョン等)に複数機能をまとめてブランチを切る、という使い方になります。


システム開発の仕事をする上では、単にプログラムを作れるだけでなく、開発環境についても理解する必要があります。
プログラミング研修を終えていきなりバージョン管理システムに触れると色々疑問に思うことが出てくると思いますので、今回の記事が助けになれば幸いです。

これからも、開発者のためになる記事を書いていきたいと思います!

削除する前に削除対象を確認する

データの誤削除を防ぐための作業テクニックとして、「削除する前に削除対象を確認する」というものがあります。
本番環境での作業や、試験日程がシビアな総合テストの作業等、ミスが許されない場合に特に有効です。

今回の記事では、SQLの例とUNIX/LINUXの例を挙げて紹介します。

【SQLの例】

事前にdelete文と同じ条件でselect文を打つことで、delete文のミスに事前に気付くことができます。

例えば、商品テーブルに以下のようなレコードが登録されているとします。
select * from 商品;

このテーブルについて、引き渡し先が登録されているレコード(NULLではないレコード)を削除しようとした場合、以下のようなSQL文を作成します。
delete from 商品 where 引き渡し先 is not null;
しかし、仮にここで条件文のnotを忘れると、逆に引き渡し先が登録されていないレコード(NULLのレコード)を削除してしまいます。

そこで、同じ条件で事前にSELECT文を発行します。
select * from 商品 where 引き渡し先 is not null;
このselect文を発行することで、事前に消えるレコードを見ることができます。
今回の例では以下のレコードが消えることを確認できます。

【UNIX/LINUXの例】

rmコマンドを-fオプション無しで対話式で削除するにはファイル数が多すぎる場合において、事前にrm -fコマンドと同じ対象にls -lコマンドを発行することで、削除対象のミスに事前に気付くことができます。

例えば、dir1というディレクトリを削除したい場合、いきなりrm -rfコマンドを発行するのではなく、事前にdir1に対してls -lコマンドを発行します。
(下位ディレクトリも確認したい場合は、ls -lRコマンドを発行します)

これで事前にどのようなファイルが削除されるのかを確認することができるため、問題がなければ「ls -l」を「rm -rf」に置き換えて実行します。