Bash 機能パッチ

Bash 機能パッチ

シェル関数(deactivate()Python virtualenvで定義された関数)があり、実行前後にいくつかのステートメントを挿入してパッチを適用したいと思います。私の目標は、deactivate()既存の関数の機能を実行し、はるかに多くの作業を実行する新しい関数を作成することです。これを行う方法はありますか?

元の関数はさまざまな場所(個々のvirtualenv)で動的に定義されているため、すべてのソースでそれらを変更することは魅力的なオプションではありません。

答え1

十分であれば、関数より優先順位の高い無効化エイリアスを生成できます。以前はコマンドを実行できますが、後で実行するのは簡単ではないからです。

alias deactivate='before; deactivate'

あるいは、単純に(より良い)より単純な名前で関数を作成します。

deact(){ [[ $somevar == true ]] && deactivate
         [[ $othervar == admin ]] && sudo deactivate
       }

または実装したいものは何でも。はい、定義されている場合にのみ実行されます。これは用語に代わるものではなく、deactivate他のユーザーには使用できません。

唯一の方法は、名前がdeactivateエイリアスまたは関数よりも優先順位の低い実行可能プログラムを作成することです。どちらも定義しないでください。

答え2

シェルがある場合、または組み込み関数を利用できる場合は、関数bashのソースコードが表示されますzshksh93typeset -f

# usage patch_func funcname before after
function patch_func {
        typeset nl=$'\n' lb={ src=`typeset -f "$1"` before=$2 after=$3
        src="${src/$lb/$lb$nl    $before$nl}"
        src="${src%\}*}$nl    $after$nl}"
        eval "$src"
}

例:

$ deactivate(){ echo -n "{$0}"; for i; do echo -n " {$i}"; done; echo; }
$ patch_func deactivate 'echo before' 'echo after'
$ typeset -f deactivate
deactivate ()
{
    echo before;
    echo -n "{$0}";
    for i in "$@";
    do
        echo -n " {$i}";
    done;
    echo;
    echo after
}

もちろん、これは非常に脆弱です。

答え3

この答えは使用法に直接適用されませんが、virtualenv使用法はどうですかvirtualenvwrapper?基本的にvirtualenvステロイドのための環境管理です。インストール後、次の追加のコマンドセットが提供されます。

  • workon引数なしで呼び出すときに使用可能なすべての環境を一覧表示し、env名を引数として使用して呼び出すときにenvを有効にしworkon myenvますmyenv
  • mkvirtualenv myenv新しい環境を作成しますmyenv
  • rmvirtualenv myenv削除してください。

しかし、それ以上があります。virtualenvwrapper独自の envs カスタムロジックを実装できる有用なフックセットが定義されています。たとえば、次のようになります。

  • premkvirtualenv環境が作成されたがまだアクティブでない場合に実行されます。
  • postmkvirtualenvenvが作成されアクティブになったときに実行されます。
  • preactivateenv アクティベーションがトリガされると実行されます。
  • postactivateenvが有効になると実行されます。
  • predeactivate環境の無効化がトリガされると実行されます。
  • postdeactivateenv が無効の場合に実行されます。

もっとあります。たとえば、新しい環境にフックがインストールされてpostmkvirtualenvいます。ipython

$ cat $VIRTUALENVWRAPPER_HOOK_DIR/postmkvirtualenv
#!/bin/bash
# This hook is sourced after a new virtualenv is activated.

env=$(basename "$VIRTUAL_ENV")
logger -s -t "($env)" "installing ipython ..."
"$VIRTUAL_ENV/bin/pip" install ipython --quiet

envを無効にするための追加ロジックを定義するには、カスタムbashスクリプトを作成し、その内容を$VIRTUALENVWRAPPER_HOOK_DIR/predeactivate(envがまだアクティブな状態でジョブを実行する必要がある場合)または$VIRTUALENVWRAPPER_HOOK_DIR/postdeactivate(envを無効にする必要がある場合はカスタムコードの実行)に配置する必要があります。します。

参考までに:virtualenvwrapper文書

フックの完全なリストについては、以下を参照してください。ユーザー固有のカスタマイズ

関連情報