読者です 読者をやめる 読者になる 読者になる

CodeIQ Blog

自分の実力を知りたいITエンジニア向けの、実務スキル評価サービス「CodeIQ(コードアイキュー)」の公式ブログです。

UNIX問題「コマンドを定期的に自動実行させよう!」解説記事 #unix #cron

問題解説

CodeIQ中の人、millionsmileです。

空飛ぶデータサイエンティストであり、好きな数式はξ|ξ′⟩=ξ′|ξ′⟩という川頭信之さんからのUNIX問題の解説です!

==============================
問題作成者の川頭です。

日常仕事をしていると、ある一定の処理を定時に自動実行させたいということがよくあります。UNIXではcronというコマンドスケジューラーが存在し、決められた時間にコマンドを実行させることができます。今回はこのcronの問題を考えてみました。

問題

cron でユーザーのディスク使用量管理
管理しているサーバーの全ユーザーのディスク使用状況を知りたいと思い、毎日定時にディスク使用量のログを取ることにしました。


UNIX のcron 機能 を使って、定期的に各ユーザーのディスク使用量の情報を取得する設定をしてください。


詳細は以下の通りです。
・/home の下にある全ユーザーのディレクトリ内の使用量をdu を使って求めてください。
・毎日23:30に情報を取得してください。
・ファイルは、/var/lib/bak に保存し、名前はdu-YYYYMMDD.log のようにしてください。
 例えば、2013年4月31日ならば、/var/lib/bak/du-20130431.log となります。
 日付の生成にはdateコマンドを使ってください。
・crontab -e で編集し、設定は crontab -e 内の一行のみで実現させてください。
 他のスクリプトファイルを読みに行くようなことはしないでください。
・使用するシェルはbashです。


解答のポイント
問題のプログラムのポイントは以下の4点です。
1. cronによるコマンド自動実行の理解
2. du, dateのオプションの理解
3. シェルのコマンド展開機能の理解
4. 実行権限

解説

1. cronとは

cronはUNIXの標準的なコマンドスケジューラーです。裏ではcrondというcronのデーモンが動いています。起動していなければ、管理者権限で/usr/sbin/service cron startや/etc/rc.d/init.d/crond startで起動してください。
crontab -eでエディタが起動し、crontab -l で設定したコマンドを見ることができます。

解答例は以下のようになっています。
$ 30 23 * * * du -s /home/* > /var/lib/bak/du-`date +"\%Y\%m\%d"`.log

分、時、日、月、曜日の順にスペースで区切って時間を指定し、指定したプログラムやコマンドを実行させます。
毎日の23:30に実行させたければ、解答例のように 30 23 * * * となります。毎日5分毎に実行させたければ、 */5 * * * * のように書くこともできます。

2. du

/home 以下のサブディレクトリのディスク使用量を求めるには du を使います。その際に -s オプションと/home/ディレクトリの後にアスタリスク”*”をつけるのがミソです。
$ du -s /home/*
三分一ぐらいの挑戦者が -d 1 オプションをつけていました。この場合はサブディレクトリ以外にもディレクトリ全体の使用量も出てきましたが、正答としました。
$ du -d 1 /home

3. コマンド展開

この問題ではファイル名がdu-YYYYMMDD.logとなり、日付が入るため、コマンドを実行する度に日付を自動生成しなければなりませんでした。ここの部分が一番難しかったと思います。

YYYYMMDDを作るためにdate +”%Y%m%d”のコマンドが必要となります。フォーマットのダブルクウォーテーションは省略できます。これをコマンド展開のバッククウォーテーション記号” `”で囲んで、ファイル名に埋め込めばOKです。ファイル名の確認は以下のようになります。
$ echo /var/lib/bak/du-`date +“%Y%m%d”`.log

du の結果を上のファイルに書き出せば完了です。
$ du -s /home/* > /var/lib/bak/du-`date +"%Y%m%d"`.log

ところが、これでOKかと思ったら、cronに実装してみると思わぬ伏兵がいました。

bashスクリプト実行では、`date +"%Y%m%d"`でコマンド展開がうまく行きますが、cronの中ではフォーマットの%を\でエスケープしないと正常に動作しないのです。半分以上の挑戦者がエスケープを忘れたために討ち死してしまいました。

下記のURLも参考にしてください。
http://maruta.be/intfloat_staff/67

4. 実行権限

UNIXではマルチユーザーが前提となっており、実行者と管理者が別の場合があるので、今回の問題ではいろいろな不明確な点がありました。私が最初に問題を考えたときは全く実行権限について考えていませんでした。挑戦者からの指摘やコマンドを実装してみて設問の実行権限について不明確な点があることに気づきました。多くの挑戦者を迷わせてしまい、申し訳なく思っています。

全体としては、cron 内でのdateフォーマットのエスケープコードの入れ忘れが多かったです。実際に実装してみないと実行できるかどうかは分からないというのがやはりコンピュータの融通の利かないところだと思います。

何かと不明な点もありましたが、楽しめたのではないでしょうか。これからも挑戦待ってます!

https://codeiq.jp/ace/kawagashira_nobuyuki/q294
f:id:codeiq:20130621190259p:plain

==============================

川頭さんは、UNIX問題以外にも、自然言語処理問題やアッカーマンの呪い問題など楽しい問題を出していますので、挑戦してみては?
https://codeiq.jp/ace/kawagashira_nobuyuki/

エンジニアのための新しい転職活動!CodeIQのウチに来ない?の特集ページを見る