【问题标题】:logging blocks of code to log files in bash记录代码块以在 bash 中记录文件
【发布时间】:2011-07-11 20:09:54
【问题描述】:

我有一个巨大的 bash 脚本,我想将特定的代码块记录到一个特定的小型日志文件(而不是一个巨大的日志文件)。

我有以下两种方法:

# in this case, 'log' is a bash function

# Using code block & piping
{
# ... bash code ...
} | log "file name"

# Using Process Substitution
log "file name" < <(
     # ... bash code ...
)

这两种方法都可能会干扰 bash 脚本的正确执行,例如为变量赋值时(如here 提出的问题)。
您如何建议将命令的输出记录到日志文件中?


编辑: 这是我尝试做的(除了许多其他变体),但没有按预期工作:

function log()
{
    if [ -z "$counter" ]; then
        counter=1
        echo "" >> "./General_Log_File" # Create the summary log file
    else
        (( ++counter ))
    fi
    echo "" > "./${counter}_log_file"   # Create specific log file

    # Display text-to-be-logged on screen & add it to the summary log file
    #  & write text-to-be-logged to it's corresponding log file
    exec 1> >(tee "./${counter}_log_file" | tee -a "./General_Log_File") 2>&1
}

log # Logs the following code block
{
    # ... Many bash commands ...
}

log # Logs the following code block
{
    # ... Many bash commands ...
}

执行结果各不相同:有时会创建日志文件,有时则不会(这会引发错误)。

【问题讨论】:

    标签: bash logging


    【解决方案1】:

    你可以试试这样的:

    function log()
    {
        local logfile=$1
        local errfile=$2
        exec > $logfile
        exec 2> $errfile    # if $errfile is not an empty string
    }
    
    log $fileA $errfileA
    echo stuff
    log $fileB $errfileB
    echo more stuff
    

    这会将所有 stdout/stderr 从当前进程重定向到没有任何子进程的文件。

    编辑:以下可能是一个很好的解决方案,但未经测试:

    pipe=$(mktemp)
    mknod $pipe p
    exec 1>$pipe
    
    function log()
    {
        if ! [[ -z "$teepid2" ]]; then
            kill $teepid2
        else
            tee <$pipe general_log_file &
            teepid1=$!
            count=1
        fi
    
        tee <$pipe ${count}_logfile &
        teepid2=$!
        (( ++count ))
    }
    
    log
    echo stuff
    log
    echo stuff2
    
    if ! [[ -z "$teepid1" ]]; then kill $teepid1; fi
    

    【讨论】:

      【解决方案2】:

      感谢Sahas,我设法实现了以下解决方案:

      function log()
      {
          [ -z "$counter" ] && counter=1 || (( ++counter ))
      
          if [ -n "$teepid" ]; then
              exec 1>&- 2>&-  # close file descriptors to signal EOF to the `tee`
                      #  command in the bg process
              wait $teepid # wait for bg process to exit
          fi
          # Display text-to-be-logged on screen and
          #  write it to the summary log & to it's corresponding log file
          ( tee "${counter}.log" < "$pipe" | tee -a "Summary.log" 1>&4 ) &
          teepid=$!
          exec 1>"$pipe" 2>&1 # redirect stdout & stderr to the pipe
      }
      
      # Create temporary FIFO/pipe
      pipe_dir=$(mktemp -d)
      pipe="${pipe_dir}/cmds_output"
      mkfifo "$pipe"
      exec 4<&1   # save value of FD1 to FD4
      
      log # Logs the following code block
      {
          # ... Many bash commands ...
      }
      
      log # Logs the following code block
      {
          # ... Many bash commands ...
      }
      
      if [ -n "$teepid" ]; then
          exec 1>&- 2>&-  # close file descriptors to signal EOF to the `tee`
                  #  command in the bg process
          wait $teepid # wait for bg process to exit
      fi
      

      它有效 - 我测试过。

      参考资料:

      【讨论】:

        【解决方案3】:

        对于 bash 代码块的简单重定向,不使用专用函数,请执行以下操作:

        ( 
          echo "log this block of code"
          # commands ...
          # ...
          # ...
        ) &> output.log
        

        【讨论】:

          猜你喜欢
          • 2014-05-17
          • 1970-01-01
          • 2012-05-17
          • 2011-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多