0

ときどき、特定のコマンドを実行しているときに、間違ったパラメーターをコマンドに送信したことに気付くことがあります (Heroku アプリケーションの再起動など)。特定の文字列を含むコマンドが検出された場合に、確信があるかどうかを確認するプロンプトが表示されるように bash を変更したいと考えています。例(文字列が tempus であると想像してください):

$ heroku restart --app tempus

ここで、bash に Y/N プロンプトを表示させたいと思います。入力した場合にyのみ、コマンドを実行します。N と入力すると、コマンドは実行されません。どうすればこの問題を処理できますか?

4

4 に答える 4

6

すべての bash コマンドを傍受する方法はわかりませんが、次のトリックを使用して所定のコマンドを傍受できます。

  1. ディレクトリを作成し(たとえば~/interception)、それを最初のエントリとして設定します$PATH
  2. インターセプトするコマンドのリストと実際のコマンドへのフルパスを使用して、そのディレクトリに次のスクリプトを作成します

    [bash]$ cat intercept.sh
    #!/bin/bash
    
    # map commands to full path
    declare -A COMMANDS
    COMMANDS[heroku]=/usr/bin/heroku
    COMMANDS[grep]=/bin/grep
    # ... more ...
    
    CMD=$(basename $0)  # command used to call this script
    
    if [[ ! -z "${COMMANDS[$CMD]+x}" ]]; then  # mapping found
      # Do what you wish here. You can even modify/inspect the params.
      echo "intercepted $CMD command... "
    
      ${COMMANDS[$CMD]} $@   # run actual command with all params
    else
      echo "Unknown command $CMD"
    fi
    
  3. 同じディレクトリで、傍受したいコマンドの名前を使用して、そのスクリプトへのシンボリックリンクを作成します

    [bash]$ ln -s intercept.sh grep
    [bash]$ ln -s intercept.sh heroku
    

これで、コマンドを呼び出すたびに、そのスクリプトがシンボリック リンクを介して呼び出され、実際のコマンドを呼び出す前に入札を行うことができます。

構成ファイルからソースを取得し、$COMMANDSヘルパー コマンドを作成して構成ファイルを拡張し、シンボリック リンクを作成/削除することで、これをさらに拡張できます。次に、次のようなコマンドを使用して who セットアップを管理できます。

intercept_add `which heroku`
intercept_remove heroku
intercept_list
于 2012-09-27T13:58:30.290 に答える
2

bash自体はコマンドラインフィルターをサポートしていないため、コマンドを傍受することはできません。

これが汚い解決策です:

  1. PATHですべての実行可能ファイルを検索し、それぞれのラッパー関数を作成します。
  2. prefilter()ラッパー関数は、宣言されている場合は関数を呼び出します。
  3. 機能が失敗した場合prefilter()、コマンドはキャンセルされます。

ソース:cmd-wrap.sh

#!/bin/bash  # The shebang is only useful for debug. Don't execute this script.

function create_wrapper() {
    local exe="$1"
    local name="${exe##*/}"

    # Only create wrappers for non-builtin commands
    [ `type -t "$name"` = 'file' ] || return

    # echo "Create command wrapper for $exe"
    eval "
    function $name() {\
        if [ \"\$(type -t prefilter)\" = 'function' ]; then \
            prefilter \"$name\" \"\$@\" || return; \
        fi; \
        $exe \"\$@\";
    }"
}
# It's also possible to add pre/post hookers by install
#   [ `type -t \"$name-pre\"` = 'function' ] && \"$name-pre\" \"\$@\"
# into the dynamic generated function body.

function _create_wrappers() {
    local paths="$PATH"
    local path
    local f n

    while [ -n "$paths" ]; do
        path="${paths%%:*}"
        if [ "$path" = "$paths" ]; then
            paths=
        else
            paths="${paths#*:}"
        fi

        # For each path element:
        for f in "$path"/*; do
            if [ -x "$f" ]; then
                # Don't create wrapper for strange command names.
                n="${f##*/}"
                [ -n "${n//[a-zA-Z_-]/}" ] || create_wrapper "$f"
            fi
        done
    done

    unset _create_wrappers  # Remove the installer.
    unset create_wrapper    # Remove the helper fn, which isn't used anymore.
}

_create_wrappers

あなたの問題のためにそれを利用するには:

  1. bashでそれを調達します:

    . ./cmd-wrap.sh
    
  2. のバージョンを作成してprefilter()、引数に文字列が含まれているかどうかを確認します。

    function prefilter() {
        local a y
        for a in "$@"; do
            if [ "$a" != "${a/tempus}" ]; then
                echo -n "WARNING: The command contains tempus. Continue?"
                read y
                [ "$y" = 'Y' ] || [ "$y" = 'y' ]
                return $?
            fi
        done
        return 0
    }
    
  3. 走る

    heroku restart --app tempus
    

    だがしかし

    /usr/bin/heroku restart --app tempus
    

    ラッパー関数を利用します。

于 2012-09-27T15:23:12.257 に答える
2

最も簡単な方法は、エイリアスを使用することです。この簡単な例はあなたのために働くはずです:

これにより、引数に tempus を指定して heroku コマンドを実行できなくなります

function protect_heroku {
    # use grep to determine if the bad string is in arguments
    echo "$*" | grep tempus > /dev/null
    # if string is not in arguments
    if [ $? != 0 ]; then
        # run the protected command using its full path, so as not to trigger alias
        /path/to/heroku "$@"
    else
        # get user confirmation
        echo -n Are you sure \(y/n\)?' '
        read CONFIRM
        if [ "$CONFIRM" = y ]; then
            # run the protected command using its full path
            /path/to/heroku "$@"
        fi
    fi
}

# This is the key:
# This alias command means that 'heroku' from now refers
# to the function protect_heroku, rather than /bin/heroku
alias heroku=protect_heroku

このコードを bash プロファイル ~/.profile に入力し、ログアウトしてから再度ログインします。今後、bash は、誤って tempus で heroku を実行することから保護します。

于 2012-09-27T18:09:37.187 に答える
1

heroku最も簡単な方法は、実際の heroku を実行する前にチェックを行うスクリプトに置き換えることです。別の方法は、 の bash エイリアスを追加することですheroku

于 2012-09-27T13:37:51.813 に答える