引数に与えられたコマンドを実行して、その証跡を残す関数
引数に与えられたコマンドを実行して、その証跡を残す関数の作成。
まず、やりたいことができるかどうかの確認。
引数に与えられたコマンドを実行できるか。
$ aaa="echo sample message" $ eval $aaa sample message
基本は、これでやれそう。
次に、証跡を残すこと。
実行結果を変数に入れて、適当に出力できるようにしてみる。
$ type eval eval はシェル組み込み関数です $ $ aaa="echo sample message" $ bbb=$(eval $aaa) $ echo $bbb sample message
やりたいことは、ほぼ完成。
エラー処理各種を試す。
$ aaa="echo sample message 1>&2" $ bbb=$(eval $aaa) sample message
標準エラー出力は xxx=$() という形式では含んでくれないので、含めておこうか。
ついでに、正常な場合の Exit Status も確認。
$ aaa="echo sample message 1>&2" $ bbb=$(eval $aaa 2>&1) $ ccc=$? $ logger -t test $bbb $ tail -1 /var/log/messages May 25 08:55:37 tsrw01 test: sample message $ echo $ccc 0
コマンドが異常終了した場合の Exit Status も確認
$ ls /etc/dummy ls: '/etc/dummy' にアクセスできません: そのようなファイルやディレクトリはありません $ echo $? 2 $ $ aaa="ls /etc/dummy" $ bbb=$(eval $aaa 2>&1) $ ccc=$? $ echo "$(date +%Y/%m/%d %H:%M:%S) $bbb" > /tmp/ddd $ cat /tmp/ddd 2019/05/25 09:04:53 ls: '/etc/dummy' にアクセスできません: そのようなファイルやディレクトリはありません $ echo $ccc 2
ということで、内容を見やすく整理しつつ関数にまとめる。
#!/bin/bash pLogFile=cmd.log fnLog() { echo "$(date +'%Y/%m/%d %H:%M:%S') $*" >> ${pLogFile} } fnCmd() { fnLog "Command line: $*" # Command exec pOutput=$(eval "$*" 2>&1) pExitStatus=$? # Log output fnLog "=== standard output / standard error output =========" echo "${pOutput}" >> ${pLogFile} fnLog "=====================================================" fnLog "Exit status: ${pExitStatus}" return ${pExitStatus} }
こうしておくと、実行したコマンドの出力結果を自由に出力しつつ、戻り値も確認できる。
ログの中身は各行に必ず日時がないとヤダ……という場合は、こんな感じ。
#!/bin/bash pLogFile=cmd.log fnLog() { echo "$(date +'%Y/%m/%d %H:%M:%S') $*" >> ${pLogFile} } fnCmd() { fnLog "Command line: $*" # Command exec pOutput=$(eval "$*" 2>&1) pExitStatus=$? # Log output fnLog "=== standard output / standard error output =========" echo "${pOutput}" | while read line do fnLog "$line" done fnLog "=====================================================" fnLog "Exit status: ${pExitStatus}" return ${pExitStatus} }
個人的には、スクリプトログなんて実行が失敗した時しか見ないんだから、コマンドの出力結果に日時情報を入れるだけムダだし、紛らわしくて困ると思うんだけど……。
パッと見のキレイさの方が重要みたい。
どうせなら、4桁くらいで固定で行番号を入れてみる?
#!/bin/bash pLogFile=cmd.log fnLog() { echo "$(date +'%Y/%m/%d %H:%M:%S') $*" >> ${pLogFile} } fnCmd() { fnLog "Command line: $*" # Command exec pOutput=$(eval "$*" 2>&1) pExitStatus=$? # Log output fnLog "=== standard output / standard error output =========" i=1 echo "${pOutput}" | while read line do fnLog $(printf "%04d: %s" $i "$line") i=$(($i + 1)) done fnLog "=====================================================" fnLog "Exit status: ${pExitStatus}" return ${pExitStatus} } fnCmd "ls /etc/hosts*"
これを chk.sh に書き込んで実行してみた結果。
$ bash ./chk.sh $ cat cmd.log 2019/05/25 09:39:11 Command line: ls /etc/hosts* 2019/05/25 09:39:12 === standard output / standard error output ========= 2019/05/25 09:39:12 0001: /etc/hosts 2019/05/25 09:39:12 0002: /etc/hosts.allow 2019/05/25 09:39:12 0003: /etc/hosts.deny 2019/05/25 09:39:12 ===================================================== 2019/05/25 09:39:12 Exit status: 0 $
うーん……
他の分も、同じコマンドを実行させるように sample1.sh / sample2.sh として書き込んで実行してみる。
sample1.sh は、実行結果に日時情報のないもの。
$ [ -f cmd.log ] && rm cmd.log $ bash ./sample1.sh $ cat cmd.log 2019/05/25 09:43:56 Command line: ls /etc/hosts* 2019/05/25 09:43:56 === standard output / standard error output ========= /etc/hosts /etc/hosts.allow /etc/hosts.deny 2019/05/25 09:43:56 ===================================================== 2019/05/25 09:43:56 Exit status: 0
sample2.sh は、実行結果に日時情報を入れたもの。
$ [ -f cmd.log ] && rm cmd.log $ bash ./sample2.sh $ cat cmd.log 2019/05/25 09:47:00 Command line: ls /etc/hosts* 2019/05/25 09:47:00 === standard output / standard error output ========= 2019/05/25 09:47:00 /etc/hosts 2019/05/25 09:47:00 /etc/hosts.allow 2019/05/25 09:47:00 /etc/hosts.deny 2019/05/25 09:47:00 ===================================================== 2019/05/25 09:47:00 Exit status: 0
実行結果に、日時情報と行番号を入れたものを再度。
$ bash ./chk.sh $ cat cmd.log 2019/05/25 09:39:11 Command line: ls /etc/hosts* 2019/05/25 09:39:12 === standard output / standard error output ========= 2019/05/25 09:39:12 0001: /etc/hosts 2019/05/25 09:39:12 0002: /etc/hosts.allow 2019/05/25 09:39:12 0003: /etc/hosts.deny 2019/05/25 09:39:12 ===================================================== 2019/05/25 09:39:12 Exit status: 0 $
……こうして並べてみると、印象がすごく違うね。