BASH記録に成功したコマンドのみを保持

BASH記録に成功したコマンドのみを保持

時々私はコマンドの構文を誤解します。

# mysql -d test
mysql: unknown option '-d'
# echo $?
2

もう一度試して正しい結果を得ました。

# mysql --database test
Welcome to the MySQL monitor.
mysql >
...

ゼロ以外のエラーコードを持つ最初のコマンドが履歴に入力されるのを防ぐ方法は?

答え1

本当に欲しくないと思います。私の一般的なワークフローは次のとおりです。

  • コマンドを入力する
  • 走る
  • 失敗します。
  • 上キーを押してください
  • 編集コマンド
  • 再びジャンプ

これで、失敗したコマンドが履歴に保存されない場合は、簡単に修正して再実行することはできません。

答え2

history -d私が考えることができる唯一の方法は$PROMPT_COMMAND。このアプローチまたは他のアプローチの問題は、コマンドがエラーで終了したか、ゼロ以外の終了コードで正常に完了したかどうかを知る方法がないことです。

$ grep non_existent_string from_file_that_exists
$ echo $?
1

答え3

これを修正するために最後に間違った説明があればいいのですが、すぐに潜在的に混乱したごみになります。

私のアプローチは、失敗したコマンドを保存して後で削除する2つのステップです。

失敗したコマンドの保存:

error_handler() {
    FAILED_COMMANDS="$(history | tail -1l | cut -c -5) $FAILED_COMMANDS"
}

trap error_handler ERR

trap command signalscommandそのうちの1つがsignals「発生」すると実行されます。

$(command)command、出力を実行してキャプチャします。

このコードは、コマンドが失敗したときに記録量をキャプチャします。最後のコマンドを履歴に保存、後で削除できるように変数に保存します。

単純ですが、変数の1つがコマンドが履歴に保存されていない場合と一緒にHISTCONTROL使用すると正しく機能しません。HISTIGNORE履歴に保存された最後のコマンドの履歴番号は前のコマンドのコマンドなので、間違ったコマンドが履歴に保存されていない場合は、前のコマンドが削除されます。

この場合、うまく機能する少し複雑なバージョンは次のとおりです。

debug_handler() {
    LAST_COMMAND=$BASH_COMMAND;
}

error_handler() {
    local LAST_HISTORY_ENTRY=$(history | tail -1l)

    # if last command is in history (HISTCONTROL, HISTIGNORE)...
    if [ "$LAST_COMMAND" == "$(cut -d ' ' -f 2- <<< $LAST_HISTORY_ENTRY)" ]
    then
        # ...prepend it's history number into FAILED_COMMANDS,
        # marking the command for deletion.
        FAILED_COMMANDS="$(cut -d ' ' -f 1 <<< $LAST_HISTORY_ENTRY) $FAILED_COMMANDS"
    fi
}

trap error_handler ERR
trap debug_handler DEBUG

後で保存した内容を削除するコマンド:

exit_handler() {
    for i in $(echo $FAILED_COMMANDS | tr ' ' '\n' | uniq)
    do
        history -d $i
    done
    FAILED_COMMANDS=
}

trap exit_handler EXIT

説明する:

Bashを終了するときは、各固有の履歴番号に対してその履歴エントリを削除し、削除されたコマンド
からFAILED_COMMANDS履歴番号を継承するコマンドを削除しないようにします。

繰り返さないと確信している場合は、FAILED_COMMANDS単に繰り返すことができます
(例:write for i in $FAILED_COMMANDS)。ただし、最大から最小までソートしないようにするには(この場合は常にそうです)uniqに置き換えてくださいsort -rnu

履歴の数字はFAILED_COMMANDS一意でなければならず、項目を削除すると次のコマンドの数字が変わるため、最大から小さいものまで順番を指定する必要があります。を発行すると、history -d 2項目3が項目2になり、項目4が項目3になる式に進みます。

したがって、このコードを使用すると、保存された最大数以下のhistory -d <n>
場所をnFAILED_COMMANDS
手動で呼び出すことができず、コードが正しく機能することを期待できません。

exit_handlerフッキングはおそらく良い考えEXITですが、事前にいつでも呼び出すことができます。

関連情報