【问题标题】:Bash script - Modify output of command and print into fileBash 脚本 - 修改命令的输出并打印到文件中
【发布时间】:2022-02-04 20:04:54
【问题描述】:

我正在尝试获取指定命令的文本输出,以某种方式对其进行修改(例如,在输出前添加前缀)并打印到文件(.txt 或 .log)中

LOG_FILE=...
LOG_ERROR_FILE=..
command_name >> ${LOG_FILE} 2>> ${LOG_ERROR_FILE}

我想在一行中修改将返回的命令并将其打印到文件中。 错误输出和常规输出的情况相同。

我是 bash 脚本的初学者,所以请理解。

【问题讨论】:

标签: bash logging sh stdout stderr


【解决方案1】:

创建一个函数来执行命令并将标准输出捕获到变量。

function execCommand(){
  local command="$@"
  {
    IFS=$'\n' read -r -d '' STDERR;
    IFS=$'\n' read -r -d '' STDOUT;
  } < <((printf '\0%s\0' "$($command)" 1>&2) 2>&1)
}

function testCommand(){
    grep foo bar
    echo "return code $?"
}

execCommand testCommand
echo err: $STDERR
echo out: $STDOUT

execCommand "touch /etc/foo"
echo err: $STDERR
echo out: $STDOUT

execCommand "date"
echo err: $STDERR
echo out: $STDOUT

输出

err: grep: bar: No such file or directory
out: return code 2
err: touch: cannot touch '/etc/foo': Permission denied
out:
err:
out: Mon Jan 31 16:29:51 CET 2022

现在你可以修改 $STDERR & $STDOUT

execCommand testCommand &&  { echo "$STDERR" > err.log; echo "$STDOUT" > out.log; }

解释:Look at the answer from madmurphy

【讨论】:

  • 这对我来说是最好的解决方案。太感谢了。我分析了这段代码,它很棒:)
  • 您能否准确解释一下 execCommand 的工作原理。我不确定 IFS,在块语句之后写入变量和行 - 它是如何工作的。
  • @treekt : 点击链接
【解决方案2】:

管道| 和/或重定向&gt; 似乎是答案。

因此,作为一个虚假示例来说明我的意思:要获取命令 ip a 吐出的所有接口,您可以将其通过管道传递给处理命令并将输出重定向到文件中。

ip a | awk -F': *' '/^[0-9]/ { print $2 }' > my_file.txt

如果您希望将其发送到单独的处理,您可以重定向到子外壳:

$ command -V cd curl bogus > >(awk '{print $NF}' > stdout.txt) 2> >(sed 's/.*\s\(\w\+\):/\1/' > stderr.txt)
$ cat stdout.txt 
builtin
(/usr/bin/curl)
$ cat stderr.txt 
bogus not found

但在单独的步骤中处理可能会更好地提高可读性:

$ command -V cd curl bogus >stdout.txt 2>stderr.txt
$ sed -i 's/.*\s//' stdout.txt
$ sed -i 's/.*\s\(\w\+\):/\1/' stderr.txt
$ cat stdout.txt 
builtin
(/usr/bin/curl)
$ cat stderr.txt 
bogus not found

有无数种方法可以按照您的要求去做,我想情况将不得不决定使用什么,但这是一个开始。

【讨论】:

    【解决方案3】:

    要修改输出并将其写入文件,同时以不同的方式修改错误流并写入不同的文件,您只需要适当地操作文件描述符。例如:

    #!/bin/sh
    # A command that writes trivial data to both stdout and stderr
    cmd() {
            echo 'Hello stdout!'
            echo 'Hello stderr!' >&2
    }
    
    
    # Filter both streams and redirect to different files
    { cmd 2>&1 1>&3 | sed 's/stderr/cruel world/' > "$LOG_ERROR_FILE"; } 3>&1 |
         sed 's/stdout/world/' > "$LOG_FILE"
    

    技术是将错误流重定向到标准输出,以便它可以流入管道 (2&gt;&amp;1),然后将输出流重定向到辅助文件描述符,该文件描述符被重定向到不同的管道。

    您可以通过将文件重定向移动到较早的 exec 调用中来稍微清理一下。例如:

    #!/bin/sh
    cmd() {
            echo 'Hello stdout!'
            echo 'Hello stderr!' >&2
    }
    
    exec > "$LOG_FILE"
    exec 2> "$LOG_ERROR_FILE"
    
    # Filter both streams and redirect to different files
    { cmd 2>&1 1>&3 | sed 's/stderr/cruel world/' >&2; } 3>&1 | sed 's/stdout/world/'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 2022-01-04
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多