IT技术博客大学习 共学习 共进步

在 shell 脚本里打日志

Solrex Shuffling 2010-12-21 23:14:12 浏览 6,041 次

今天小弟在重构代码中的一个脚本模块,其中涉及到日志功能。上午花了点儿时间想出了个在 shell 打日志的技巧,觉得值得写一下。

希望要实现的效果是:实现一个 write_log 命令,给一条出错消息作为输入,write_log 记录日志时自动加上 时间戳、脚本文件名和行号。形如:

2010-12-17 19:13:44 [work.sh:24] FATAL: mkdir -p /x.

时间戳、脚本文件名都好获得,但是行号就没那么容易实现了。shell 中的 $LINENO 变量只能展开成当前行的行号,如果把 write_log 实现成函数的话,势必在函数中无法使用 $LINENO。

开始我想了好大一会儿,觉得 eval 能干这个事情。但是如果用 eval 的话,还不如直接把 $LINENO 传给 write_log 函数呢,与我的初衷不是太相符。我拉来同事讨论了一把,也没解决问题。正当我准备放弃了,计划每次传 $LINENO 参数时,忽然想起来,怎么把 alias 给忘了呢?

于是,write_log 的实现就是这个样子了:

function _write_log()
{
  if [ $# -eq 2 ]; then
    if [ -z $LOGFILE ]; then
      echo "$(date "+%Y-%m-%d %H:%M:%S") [$0:$1] $2"
    else
      echo "$(date "+%Y-%m-%d %H:%M:%S") [$0:$1] $2" >> $LOGFILE
    fi
  elif [ $# -eq 1 ]; then
    if [ -z $LOGFILE ]; then
      echo "$(date "+%Y-%m-%d %H:%M:%S") [$0] $1"
    else
      echo "$(date "+%Y-%m-%d %H:%M:%S") [$0] $1" >> $LOGFILE
    fi
  else
    return 1
  fi
}
alias write_log='_write_log $LINENO' # 这里必须使用单引号

存在的问题是:上面这段代码在 bash 里是不工作的,但是用 sh 可以――即使 sh 也是链接到 bash 的。问题出在 alias 上,可以把问题简化成这样,有一个脚本 a.sh:

$ cat a.sh
alias lss='ls -l'
lss /tmp

这个脚本用 /bin/sh 执行是这样的:

$ sh a.sh
total 8
drwx------ 2 gdm gdm 4096 2010-12-17 19:34 orbit-gdm
drwx------ 2 gdm gdm 4096 2010-12-17 11:04 pulse-PKdhtXMmr18n

用 /bin/bash 执行是这样的:

$ bash a.sh
a.sh: line 2: lss: command not found

把 bash 随便 link 成一个叫 sh 的链接文件,再执行是类似这样的:

$ ln -s /bin/bash ~/sh
$ ~/sh a.sh
total 8
drwx------ 2 gdm gdm 4096 2010-12-17 19:34 orbit-gdm
drwx------ 2 gdm gdm 4096 2010-12-17 11:04 pulse-PKdhtXMmr18n

这个问题肯定是有原因的,我不愿意去翻 bash 源代码,也不知道哪里去找答案,所以我放弃了,直接在文件头加上

#!/bin/sh

如果哪位兄台知道这种“奇怪”现象的原因所在,请不吝赐教

建议继续学习

  1. server日志的路径分析 (阅读 11,140)
  2. AWStats简介:Apache/Windows IIS的日志分析工具的下载,安装,配置样例和使用(含6.9中文定义补丁) (阅读 9,960)
  3. 利用脚本分析日志并利用snmp自定义OID,再通过cacti画图 (阅读 9,921)
  4. tomcat catalina.out日志切割每天生成一个文件 (阅读 9,120)
  5. 分布式日志系统scribe使用手记 (阅读 8,840)
  6. 你可能不知道的Shell (阅读 8,161)
  7. AWStats是一个基于Perl的WEB日志分析工具。 (阅读 7,040)
  8. 使用nginx记日志 (阅读 6,600)
  9. 面向对象的Shell脚本 (阅读 5,981)
  10. Bash如何取得当前正在执行的脚本的绝对路径? (阅读 5,841)