bash_history:危険なコマンドをコメントアウト: `#`


16

bash履歴に「危険な」コマンドが記録されないように、.bashrcファイルに次の行を追加しました。

HISTIGNORE='rm *:mv *:cp *:cat*>*:pv*>*'

これはうまく機能しますが、副作用があります。マシンで実行されたコマンドの完全な履歴が表示されません。実験用に複数のマシンがあり、実行されたすべてのコマンドを表示できるようにしたいとします。bash internal historyを使用して実行されたコマンドを表示し、おそらく今日の日付のgrepを使用します。

history | grep Sep-28

私がしたいのは、「危険な」コマンドもログに記録#することですが、行の先頭にa を付けて、誤って履歴からコマンドを実行しても、損害が発生しないようにすることです。

これが可能かどうかはわかりません。

更新と説明:

これが私にとって問題である主な理由は、私は通常複数の端末からマシンに接続されており、1つの端末で実行されたコマンドはすぐに他の端末の履歴に読み込まれるからです。これは以下によって達成されます

PROMPT_COMMAND="history -a; history -c; history -r"

私が2つの端末を開いていると想像してみましょう。1つでは、いくつかのcat /dev/foo > file.outプロセスを実行しています。2番目では、で進行状況を確認しls -lAhFます。and (つまり、履歴の最後のコマンド)をls押して繰り返します。すぐに最初のコマンドが終了するなどとして、歴史からの最後のコマンドは、もはやありませんが、。注意しないと、catを再び起動してfile.outを上書きします。UpENTERlscat /dev/foo > file.out

私が達成したいのは、catコマンドの前にを付けて#、実行されないようにすることです。しかし、私はまだ履歴に表示し、コメントを外すことで(長いコマンドの場合)再利用できます。


コマンドを手動で繰り返す代わりに、watch ls -lAhFまたはを使用できますwhile sleep 1; do ls -lAhf; done。ファイルサイズを監視する代わりにpv /dev/foo > file.outivarch.com/programs/pv.shtml)を使用できます。
デルタブ14年

回答:


9

次のようなことができます:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%[*/]*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

各プロンプトの前に、最後の履歴エントリ(history 1)をチェックし、それが危険なエントリの1つである場合、それを削除(history -d)し、#withで追加し直すという考え方history -sです。

(明らかに、HISTIGNORE設定を削除する必要があります)。

そのかかわらの不要な副作用は、それが変化させることである歴史の時間これらのrmmv...コマンドを。

これを修正するための代替手段は次のとおりです。

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

今回は、最後の履歴の時刻を記録し、履歴行を追加するためhistory -rに、タイムスタンプを含む一時ファイル(ヒアドキュメント)から使用します。

あなたはあなたのfixhist前に実行されたいでしょうhistory -a; history -c; history -r。残念ながら、現在のバージョンにbashはバグhistory -aがあり、追加した余分な行は保存されません。回避策は、代わりにそれを書くことです:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

つまり、コメント化されたコマンドをHISTFILEに追加するのではなく、自分で追加しますhistory -a


何を説明してもらえますcmd=${cmd#*[0-9] }か?そして、場所を正確に私が入れなければならないfixhist私にPROMPT_COMMAND?現時点では、すでに含まれていますPROMPT_COMMAND="history -a; history -c; history -r"
マーティンベグター14年

の役割はHISTTIMEFORMAT=/何ですか?私はすでに設定しましたexport HISTTIMEFORMAT="%b-%d %H:%M "。ところで、にコードを追加しても$HOME/.bashrc、何も起こりません。
マーティンVegter 14年

HISTTIMEFORMAT=/cmdを抽出しやすい場所historyなどの出力を取得するための1回の呼び出しのみです123 /rm x。そのコンテキストのbashどこ$HISTCMDが偽物だったかのいくつかのバージョンに問題がありました。新しいバージョンを試してください。
ステファンシャゼル14年

それでも動作しません。私は#、コード内のコメントとして機能しないの.bashrcだろうか?
マーティンVegter 14年

1
@MartinVegter、はい、変更された履歴エントリに対して、予期しない履歴番号の後にbasha *を挿入します。今すぐ修正する必要があります。
ステファンシャゼル14

11

私はあなたの質問に正確に答えるつもりはありませんが、あなたの問題に対する代替解決策を提供するかもしれません。

私が正しく理解していれば、タイプすることで犯す可能性のある間違いについて心配しています。例えば、履歴!rmの前のrmコマンドが保持したいものを削除してしまった場合です。

この場合、素敵なbashオプションはhistverifyです。あなたならばshopt -s histverify、あなたがバタンとコマンドを呼び出した場合、そして!、それはすぐに実行されませんが、あなたはどちらかそれを実行するかどうかを決めることができるようにreadlineの中にロードされ、これはまた、あなたの編集、それへの可能性を提供します。

それを試してみてください:

  • なしhistverify

    $ touch some_foo
    $ rm some_foo
    $ touch some_foo
    $ !rm
    rm some_foo
    $ # oooops in fact I'd've like to keep it this time
  • histverify

    $ shopt -s histverify
    $ touch some_foo
    $ rm some_foo
    $ touch some_foo
    $ !rm
    $ rm some_foo <cursor here>

    この場合、行の最後にカーソルがあり、再度起動するかどうか、または編集する準備ができています。

このオプションが気に入ったら、次のようにしてください.bashrc

shopt -s histverify
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.