すべてのコマンドに「追加された」エイリアスを強制する


11

のすべてのコマンドにタイミングエイリアスを強制的に追加することはできbashますか(それを表現するためのより良い方法がないため)?

たとえば、特定のユーザーがコマンドを実行するたびに、常にdate前後またはでラップされるようにしたいと考えていますtime

これは可能ですか?可能な場合、どのようにですか?


私は前を見て、これを正確に行う方法を見つけることができませんでした。Calebが言うように、を使用することはできますpreexecが、preexec(たとえばpreexec() { time $1; })内で実行したくないのは、シェルがpreexec戻った後も実行するためです。したがって、私たちにできる最善のことは同様のことです。
ミケル

@Mikel preexec()関数を使用して、コマンドをフェッチし、関数内から自分で実行し、シェルがコマンド自体を実行しないように何らかのエラーを返すことで、実行されているものを実際にラッパーできると思います。
カレブ2012

回答:


10

コマンドラインが開始された時刻とプロンプトが表示された時刻を記録できます。Bashはすでに各コマンドラインの開始日を履歴に記録しており、次のプロンプトを表示する時刻を記録できます。

print_command_wall_clock_time () {
  echo Wall clock time: \
    $(($(date +%s) - $(HISTTIMEFORMAT="%s ";
                       set -o noglob;
                       set $(history 1); echo $2)))
}
PROMPT_COMMAND=print_command_wall_clock_time$'\n'"$PROMPT_COMMAND"

これは、2番目の解像度と壁時計時間のみを提供します。より良い解像度が必要な場合dateは、%Nナノ秒の形式をサポートする外部コマンドと、コマンドを実行する前DEBUGに呼び出すトラップを使用する必要がありますdate

call_date_before_command () {
  date_before=$(date +%s.%N)
}
print_wall_clock_time () {
  echo Wall clock time: \
    $((date +"$date_before - %s.%N" | bc))
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_command_wall_clock_time

でもでDEBUGトラップ、私は自動的にコマンドごとのプロセッサ時間を表示する方法はないと思う、またはそれ以上のプロンプトにプロンプトよりも識別されています。


別のシェルを使用する場合は、zshのすべてのコマンドの時間レポートを取得する方法を以下に示します(これは他のタスクに一般化されません)。

REPORTTIME=0

REPORTTIME任意の整数値に設定できます。タイミング情報は、この秒数を超えるプロセッサー時間を使用したコマンドに対してのみ表示されます。

Zshは、変数が呼び出されるcshからこの機能を採用しましたtime


3

ここでのオプションは、シェルによって異なります。zsh呼ばれる便利なフック関数がpreexec()右の任意の対話型シェルコマンドの前に実行されます。この名前で関数を作成することで、物事を実行させることができます。コマンドが終了したprecmd()直後に次のプロンプトが表示される直前に実行されるという関数を呼び出すこともできます

この関数のペアを作成することにより、プロンプトで発行されるコマンドの前後に任意のコマンドを実行できます。これを使用して、シェルの使用状況のログ、ロックの作成、環境のテスト、または例のように、コマンドの実行中に費やされた時間またはリソースを計算できます。

この例では、を使用してコマンドを実行する前に自分自身でベンチマークタイムスタンプを作成し、preexec()を使用precmd()してコマンドの実行に費やした時間を計算し、プロンプトまたはログアウトする前に出力します。例:

preexec() {
   CMDSTART=$(date +%s%N)
}
precmd() {
   CMDRUNTIME=$(($(date +%s%N)-$CMDSTART))
   echo "Last command ran for $CMDRUNTIME nanoseconds."
}

注:この特定の例では、さらに簡単な組み込み関数があります。あなたがしなければならないのはZSHでランタイムレポートをオンにすることだけです、そしてそれはそれを自動的に行います。

$ export REPORTTIME=0
$ ls -d
./
ls -BF --color=auto -d  0.00s user 0.00s system 0% cpu 0.002 total

のより実際的な実装ではpreexec()、シェルが内部で実行されているtmuxscreenどうかを確認し、そうである場合は、現在実行中のコマンドに関する情報を上流に送信してタブ名に表示します。

残念ながらbashでは、この小さなメカニズムは存在しません。これを再現しようとするある人の試みを次に示します。同様の気の利いた小さなハックについてのGillesの回答も参照してください。




これがbashで利用可能になったといいのですが!
ウォーレン

Gillesと他のリンクを参照してください。少し余分な手間を加えるだけでbashに実装できます。繰り返しますが、なぜzshを実行しないのですか?これは、これ以上の理由で切り替えができるロッキングシェルです!
カレブ

2
zshを使用している場合は、さらに優れた方法があります。REPORTTIME環境変数が設定されると、$ REPORTTIME秒より長い時間がかかるコマンドの実行時間情報( 'time'を前に付けてコマンドを実行したかのように)が出力されます。これを0に設定するだけで、すべてのコマンドの時間が表示され、ユーザー/システムの内訳が起動します。
ジョセフガービン

1

最も簡単な方法は、おそらく設定することでしょうPROMPT_COMMANDBash変数を参照してください。

PROMPT_COMMAND
設定されている場合、値は各プライマリプロンプト($PS1)の印刷前に実行するコマンドとして解釈されます。

たとえば、既存のプロンプトコマンドを上書きしないようにするには、次のようにします。

PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"

そのことを知らなかった-良いスタートのように見えます、@ cjm
ウォーレン

1
これは始まりですが、コマンドがいつ実行されたかを知るという問題には対処していません。コマンドを入力して実行する前に、プロンプト自体が数分、数時間、または数日描画される場合があります。
カレブ2011

0

csh/ tcshは、この機能を最もよくサポートしています(そして、常にそれを持っています)。

  The `time` shell variable can be set to execute the time builtin  command
  after the completion of any process that takes more than a given number
  of CPU seconds.

つまり、 set time=11秒以上のCPU時間を要したコマンドによって消費された時間(システム、ユーザー、経過)を出力します。プレーンset timeは、すべてのコマンドの時間を出力できるようにします。

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