QA@IT

crontab の r オプションを実行できないようにしたい

5893 PV

背景

re の隣にあるため、 crontab -e を行おうとして crontab -r を実行し、設定を削除してしまうという事故が起こりやすいような気がします。

alias crontab='crontab -i'

といった alias を指定すれば crontab -rcrontab -ru ponko2crontab -u ponko2 -r すべてのパターンで解決出来るかと思ったのですが、OS Xの crontab には i オプションが存在せず、この方法では無理のようです。

crontab -l > ./crontab
vim ./crontab
crontab ./crontab

といった編集をすれば問題ないとは思いますが、 crontab に file が渡せることが私のまわりではあまり知られていないようです……

目的

上記のような編集方法を知らない人でも安全に crontab の編集ができるよう、下記の環境で共通して使用できる crontab -lcrontab -ecrontab file を生かしたまま、crontab -rcrontab -ru ponko2crontab -u ponko2 -r を実行できないようにする良い手段はありませんでしょうか?

crontab 以外にも特定のオプションを禁止したいコマンドが何個かあるため、可能な場合は汎用的な方法でご回答いただきたいです。

実行環境

  • Mac OS X 10.7.4, zsh 4.3.17
  • Ubuntu 12.04, zsh 4.3.17
  • Debian 6.0.5, zsh 4.3.10

回答

crontab をシェル関数で上書きしても良いのであれば、次のようなシェル関数を作成すれば実現できます。crontab -r を実行すると、自動で crontab -ri 相当の動作となります。crontab -r 以外の場合は通常と同じ動作になりますので、使い勝手に影響はありません。

crontab()
{
  if [[ $1 = -r ]]; then
    echo -n "crontab: really delete $USER's crontab? (y/n) "
    typeset answer
    while :; do
      read answer
      [[ $answer = (y|Y) ]] && break
      [[ $answer = (n|N) ]] && return 0
      echo -n "Please enter Y or N: "
    done
  fi
  command crontab ${1+"$@"}
}

編集 履歴 (1)
  • うーん…出来れば避けたいですねぇ -
  • 質問中でエイリアスで上書きしていますが、何故シェル関数だと避けたいのでしょうか。 -
  • 使われる機会はまず無いと思いますが「crontab -u ponko2 -r」とか「sudo crontab -u ponko2 -r」への対応もしていかなければいけなくなりますし、そんな都合の良い手段があるのかというのは別として、汎用的に使える特定オプション禁止の手段があれば知りたいという考えです。 -
  • 色んなケースすべてで禁止したいとなると、crontab コマンドを置き換えるしかないと思います。 -
  • コマンド置き換えと関数以外ですぐ思いつくものとしては、しっかりオプションを解析するためにRubyのOptionParserとか使って -r だけ無視したコマンド作って、PATHの頭の方に置いとくとかですかね。どちらにせよ特定のオプションを禁止したいコマンドが増えるごとに同じような作業が発生して非効率ですが…… -
  • こちらの質問で汎用的に使える方法がいただけなかった場合に別の質問で上げさせていただこうと思っていたのですが「ログに行った作業を確実に記録したいので sudo -s を禁止したい」といった場合等、特定オプションの実行を禁止したいような例はそれなりに数があるのではないかと思うんですよね。 -
  • 対話シェルでの操作を記録したいということですかね。シェルを改造してそのような機能を追加するか、ttyrec を挟むしかないと思います。exec(2) だけでよければ snoopy とやらでログを取れるようですが。そのように工夫しても回避のしようはいくらでもあるので、カーネルレベルでどうにかしないと「確実に」は無理かと。 -
  • 「対話シェルでの操作を記録したい」ではなく「sudoで行った作業を記録したい」ですね。それ自体は visudo の設定で可能ですが「sudo -s」で対話式シェルを起動されてしまうとその後のログが残せないので禁止したいのです。ちょっとしたシェルのスクリプトは組めるが、あまりLinuxに詳しくない人を対象としているので、回避策があっても容易なものでなければ問題ないと考えています。 -
  • それなら sudoers(5) でシェルのコマンドを「Cmnd_Alias SHELLS = /bin/*sh, /bin/??sh」のように定義して `sudo -s` などでシェルを実行させたくないユーザーを「username ALL=(ALL) ALL, !SHELLS」、グループを「%groupname ALL=(ALL) ALL, !SHELLS」とすれば禁止できます。 -
  • 「Cmnd_Alias SHELLS = /bin/*sh」に訂正。 -
  • 回答ありがとうございます。やはりSHELL全部指定するしか無いですね。 -
  • Twitterでご指摘いただきましたとおり、背景及び目的を明記し、足りない説明を追加をさせて頂きました。この度はわかりにくい質問をしてしまい、申し訳ございませんでした。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。