bash で特定のコマンドを実行前にキャンセルする
DEBUG を trap すれば、コマンド実行前に任意の処理を挟めるということがわかったので、特定のコマンドが入力されたらキャンセルできないか試してみました。
COMMANDS=$(cat <<EOC rm -rf /tmp/foobar EOC ) preexec() { [ -n "${COMP_LINE}" ] && return [ "${BASH_COMMAND}" = "${PROMPT_COMMAND}" ] && return local cmd_history=$(HISTTIMEFORMAT='%F %T%z ' history 1) #local cmdtime=$(date -d "$(echo ${cmd_history} | perl -lane 'print join(" ", @F[1 .. 2]);')" +%s) local cmd=$(echo ${cmd_history} | perl -lane 'print join(" ", @F[3 .. $#F]);') [ "${cmd}" = "" ] && return cancel "${cmd}" } cancel() { local cmd="${1}" IFS=$'\n' for cancel_cmd in $(echo ${COMMANDS}); do echo $cmd | grep -qs "${cancel_cmd}" && echo "cancelled ${cmd}" && kill -INT 0 done } trap - DEBUG trap 'preexec' DEBUG
上記を .bash_profile か .bashrc に書いておいて以下のようにコマンドを実行すると、
$ mkdir /tmp/foobar $ rm -rf /tmp/foobar cancelled rm -rf /tmp/foobar $ test -d /tmp/foobar $ echo $? 0
mkdir /tmp/foobar
は実行できていて、 rm -rf /tmp/foobar
はキャンセルできています。
ただし、これだとコマンドの引数の順番が違うとだめになってしまうので、sort して順番を揃えたほうが良さそうです。
では、CentOS6 だとだめでしたが、これを応用すると CentOS6 でも HISTFILE
にコマンドの履歴を残しつつ、history を消すことができました。
zsh には preexec hook という機能があるそうなので、trap ではなくそちらを使うと良いようです。
この設定が安全かどうかは確認できていないのでご利用の際はご注意ください(使う人いないと思いますが)。