BLOGTIMES
::
Home > crontab -r とやってしまった時の対処法
2009/11/21
[ by hsur at 20:27]

crontab -r とやってしまった時の対処法

  

cronの設定を変えようと crontab -e と打とうとして、間違って crontab -r と打ってしまい、cronの設定が根こそぎぶっ飛んで参りました。
「eとrは隣同士だから不慮の事故ですよ!」という他人の言い訳は以前から良く聞いていて、心の中で「そんなことあるかよ!」と思っていましたが、まさか自分がやってしまうとは思いませんでした。まったく言い訳できません。

仕方が無いので、/var/log/cronの実行ログからcrontabをサルベージするスクリプトを書いてみました。本当は時刻の設定とかも復元できるようにしようかと思ったのですが、まぁそんなにお世話になることもないのでそのあたりは手動で実施するということにします。いちおうリストアップされるようにしました。ユニークに出力しますが、*/5みたいに綺麗に畳んだりできないので出力は結構冗長です。

$ ./cron_salvage.rb --help
Usage: cron_salvage [options]
    -f, --file CRONLOG               cron log file (default: /var/log/cron)
    -u, --user USER                  cron user (default: root)

こんな感じで、対象のログファイルとユーザーが指定できるようにしてみました。
/var/log/cronが読める必要があるので、基本的にはrootユーザーで実行する必要があります。

$ ./cron_salvage.rb
 * * * * * /usr/lib/sa/sa1 1 1
 * * * * * ionice -c3 nice -n 19 /opt/apache/htdocs/admin/AWStats69t_Jpn/wwwroot/cgi-bin/awstats.cron > /dev/null 2>&1
 * * * * * run-parts /etc/cron.daily
 * * * * * run-parts /etc/cron.hourly
 * * * * * run-parts /etc/cron.weekly

こんな感じで、crontabが復元されるので、cron.(daily|hourly|weekly)に設定されている部分など、不必要な部分を除いてやればよいと思います。まぁ、対象がrootでなければ余計なものはあまり出てこないと思いますが。

cron_salvage.rb

突貫で作ったので、やっつけ気味です。
やっぱり時、分だけリストアップするようにしました。

#!/usr/bin/ruby
require 'optparse'
require 'time'

opts = OptionParser.new
conf = Hash.new
conf[:file] = '/var/log/cron'
opts.on("-f", "--file CRONLOG", "cron log file (default: /var/log/cron)"){ |f| conf[:file] = f }
conf[:user] = 'root'
opts.on("-u", "--user USER", "cron user (default: root)"){ |u| conf[:user] = u }
opts.parse!

unless File.exist?( conf[:file] )
  puts "logfile not found. (--file: #{conf[:file]})"
  exit 1
end

cmds = {}
open(conf[:file]) do |file|
  while line = file.gets
   month, day, time, host, proc, user, op, cmd = line.split(' ',8)
   user = user[1..-2]
   cmd = cmd[1..-3]

   next unless op == 'CMD' && user == conf[:user]
   cmds[cmd] = {} unless cmds.has_key? cmd
   cmds[cmd].store( (Time.parse("#{month} #{day} #{time}").to_a)[2..3].reverse, true)
  end
end

cmds.each do |cmd, timing|
  timing.keys.sort.each do |k|
    hour, min = k
    puts "#{min} #{hour} * * * #{cmd.gsub('%', '\%')}"
  end
end

crontabのバックアップをする

今回の件で懲りたのでcrontabのバックアップを定期的に取るようにしました。やり方的には /var/spool/cron/(username) を取るか、crontab -l の結果をリダイレクトる2通りが考えられるのですが、どちらがメジャーなんでしょうかね。

ちなみにコマンド部分で%を使おうとしてハマったのでこちらもメモ。
昔、コマンド指定でdateがどうしても使えなくて困った記憶があるんだけど、おそらくこれが原因だろうなぁ。

Manpage of CRONTAB

「第 6」フィールド (行の残りの部分) には実行されるコマンドを指定する。その行のコマンド部 (改行文字または % 文字まで) が /bin/sh (またはその crontab ファイルの SHELL 環境変数で指定されたシェル) によって実行される。コマンド中にパーセント記号 (%) がバックスラッシュ (\) によってエスケープされずに置かれていると、改行文字に置き換えられ、最初に現れた % 以降の全てのデータは標準入力としてコマンドに送られる。

2009/11/24追記

2009-11-24 - (rubikitch loves (Emacs Ruby CUI))

しかし、こんなスクリプトを書いたり、いちいちcrontab -lで確認したりする必要はない。たんに「crontab FILENAME」を実行すればそのファイルをcrontabに登録してくれる。

俺の場合、 ~/.crontab というファイルを作成し、保存と同時に登録するようにしている。

なるほど。そうか、入れてからバックアップを取るんじゃなくて、ファイルを作ってから放り込めばいいのか。考え方の順序が逆だった。
リポジトリ入れておけば、更新のログも取れて一石二鳥だし。

このエントリは役に立ちましたか?
トラックバックについて
Trackback URL:
お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
このエントリへのTrackbackにはこのURLが必要です→http://blog.cles.jp/item/3303
Trackbacks
このエントリにトラックバックはありません
Comments
愛のあるツッコミをお気軽にどうぞ。[policy]
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントはありません
Comments Form

コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。

OpenID を使ってログインすることができます。

Identity URL: Yahoo! JAPAN IDでログイン

Web Services by Yahoo! JAPANPowered by NP_SpamBayesJP
★下記に2つの英単語をスペースで区切って入力してください
::
Home > crontab -r とやってしまった時の対処法