🐚

ログにコマンドごと記録するShellの関数作ってみた

2023/09/10に公開

はじめに

コマンドの出力を記録する際にリダイレクト>はよく使う方法だと思います。ですが、この方法だと叩いているコマンドそのものを記録として残せないため下記2点がログとして残せない悩みがあります。(もちろん、PWや秘密鍵等は記録してはいけないのでここでは考えてません。)

  • 引数の記録
  • オプションの記録

そこで、シェルスクリプトの関数を用いてコマンドとログを保存するパスも一緒に記録する関数を作成しました。コマンドも一緒に残したいなぁと思いの方は.bashrc.zshrc等に記載していただけると幸いです。

シェルスクリプトの関数

log_and_run() {
    # Usageの定義
    local usage="
    Usage: log_and_run LOG_FILE command [arguments...]

    Description:
        Executes a command and logs its output to a specified log file.

    Arguments:
        LOG_FILE   The path to the file where the command output will be logged.
        command    The command to execute.
        arguments  Additional arguments to pass to the command.

    Examples:
        log_and_run /path/to/log.txt ls -l
        log_and_run /path/to/log.txt echo Hello World
    "

    # 引数のチェック
    if [ "$#" -lt 2 ]; then
        echo "$usage"
        return 1
    fi

    local log_file="$1"
    shift

    # ログファイルのディレクトリが存在しない場合、ディレクトリを作成
    mkdir -p "$(dirname "$log_file")"

    # CommandとSave Pathをログに追記
    echo -e "Command: $@\nSave Path: $log_file" >>"$log_file"

    "$@" >>"$log_file" 2>&1
}

使い方

具体例とできること

UsageExamplesに汎用例があるため、こちらでは具体例を書きます。

入力1

log_and_run ~/log/hoge.log echo abcdef

結果・確認

Command: echo abcdef
Save Path: log/hoge.log
abcdef

入力2

log_and_run log/fuga.log ls -lh log/

結果・確認

Command: ls -lh log/
Save Path: log/fuga.log
total 24
-rw-r--r--  1 kazuki.hamaguchi  staff   115B  9 10 18:32 fuga.log
-rw-r--r--  1 kazuki.hamaguchi  staff   636B  9 10 18:31 hoge.log
-rw-r--r--  1 kazuki.hamaguchi  staff   1.9K  9 10 18:24 log.txt

出来ないこと

パイプ|やリダイレクト>で繋いだコマンドの記録は対応していません。基本的に1つのコマンドに対して引数やオプションがある場合のみ対応しています。

ちょっと細かい部分の説明

シェルスクリプトで使っている"$#""$@"のちょい説明

  • "$#":関数に渡された引数の個数をカウントする
    • 関数の動作に必要な引数の数を確認する用途で使うと便利
  • "$@":関数に渡された引数をスペースごとに区切り文字列として扱う
    • 引数ありで実行したいコマンドを動的に指定する際に使うと便利

さいごに

もっと簡単にできるかなぁと考えましたが、思いつかない&あったとしてもコマンド自体を忘れやすいのでシェルスクリプトの関数で置くのが個人的に一番良かったです。関数の名前に関しては使いやすい名前に変えて使ってもらえると嬉しいです。

Discussion