【发布时间】:2019-11-15 16:32:57
【问题描述】:
我有一组 bash 日志功能,可以让我轻松地将所有输出重定向到日志文件,并在发生某些事情时退出:
#! /usr/bin/env bash
# This script is meant to be sourced
export SCRIPT=$0
if [ -z "${LOG_FILE}" ]; then
export LOG_FILE="./log.txt"
fi
# https://stackoverflow.com/questions/11904907/redirect-stdout-and-stderr-to-function
# If the message is piped receives info, if the message is a parameter
# receives info, message
log() {
local TYPE
local IN
local PREFIX
local LINE
TYPE="$1"
if [ -n "$2" ]; then
IN="$2"
else
if read -r LINE; then
IN="${LINE}"
fi
while read -r LINE; do
IN="${IN}\n${LINE}"
done
IN=$(echo -e "${IN}")
fi
if [ -n "${IN}" ]; then
PREFIX=$(date +"[%X %d-%m-%y - $(basename "${SCRIPT}")] ${TYPE}: ")
IN="$(echo "${IN}" | awk -v PREFIX="${PREFIX}" '{printf PREFIX}$0')"
touch "${LOG_FILE}"
echo "${IN}" >> "${LOG_FILE}"
fi
}
# receives message as parameter or piped, logs as info
info() {
log "( INFO )" "$@"
}
# receives message as parameter or piped, logs as an error
error() {
log "(ERROR )" "$@"
}
# logs error and exits
fail() {
error "$1"
exit 1
}
# Reroutes stdout to info and sterr to error
log_wrap()
{
"$@" > >(info) 2> >(error)
return $?
}
那我使用函数如下:
LOG_FILE="logging.log"
source "log_functions.sh"
info "Program started"
log_wrap some_command arg0 arg1 --kwarg=value || fail "Program failed"
哪个有效。由于log_wrap 重定向stdout 和sterr,我不希望它干扰使用管道或重定向组成的命令。如:
log_wrap echo "File content" > ~/user_file || fail "user_file could not be created."
log_wrap echo "File content" | sudo tee ~/root_file > /dev/null || fail "root_file could not be created."
所以我想要一种方法来对这些命令进行分组,以便解决它们的重定向问题,然后将其传递给log_wrap。我知道两种分组方式:
-
子shell:它们不是用来传递的,自然是这样的:
log_wrap ( echo "File content" > ~/user_file ) || fail "user_file could not be created."引发语法错误。
-
大括号(分组?上下文?):在命令内部调用时,大括号被解释为参数。
log_wrap { echo "File content" > ~/user_file } || fail "user_file could not be created."大致相当于(在我的理解中):
log_wrap '{' echo "File content" > ~/user_file '}' || fail "user_file could not be created."
概括地说,我的问题是:有没有办法将命令组合(在我的例子中由重定向/管道组成)传递给 bash 函数?
【问题讨论】:
标签: bash function pipe subshell