Enginear
593 文字
3 分
macOSでコマンド完了時に通知を行う

macでmakeやxcodebuild等ターミナルで実行する際時間がかかるコマンドを実行し放置している場合でも、完了時に通知センターへ通知を送る仕組みを作成した。

実現方法#

macのコマンドラインにはosascriptというAppleScriptを呼び出すコマンドが存在する為これを.zshrc内に自作関数として組み込んで実装する。

実行サンプル#

面倒であればこれをそのまま突っ込めば良い(ブラックリスト設定等は別途下部に記載)

preexec() {
    current_command=$1
    timer=${timer:-$SECONDS}
}

precmd() {
    if [[ -n $timer ]]; then
        elapsed=$(( SECONDS - timer ))
        unset timer

        local threshold=30
    local blacklist=("vi" "vim" "sgpt" "sg" "bat" "cat" "less")
    local cmd_name=$(echo $current_command | awk '{print $1}')

    if (( elapsed > threshold )) && [[ ! " ${blacklist[*]} " =~ " ${cmd_name} " ]]; then
            osascript -e "display notification \"${cmd_name}が${elapsed}秒で完了しました\" with title \"コマンド実行通知\""
        fi
    fi
}

コマンドの実行が完了した際は以下の様な通知が表示される。 コマンド実行完了時に表示される通知

設定項目#

  • threshold
    設定した時間以上コマンドが実行されている場合通知の対象とする(秒)
  • blacklist
    実行した際に通知の対象外にするコマンド(vim等)

解説#

preexec#

コマンド実行時に実行される関数
ターミナル内でコマンドを実行される直前に、実行時間から何秒経過しているかを測定する為に使用している。
timer変数内に$SECONDSを設定しているが、この環境変数はshellが起動してからの経過秒数が保持されている変数の為この時間の差を求めることで算出している。

precmd#

プロンプトが表示される直前に実行される関数(今回の場合vim等のプロンプトを離れ終了後にプロンプトへ戻る場合を想定)
プロンプトを離れていた際の時間を先程のSECONDSとtimerの差から求めてelapsedに保持。
thresholdで通知の対象とする実行時間を30秒以上に設定。
blacklist配列に通知の対象外とするコマンドを定義。
cmd_nameにて実行したコマンド名を抽出(パイプで繋いでも先頭のみ取得する)。
条件分岐で指定時間以上及びブラックリスト外の場合osascriptを実行して通知を発行する。