将 subshell 传递给 bash 函数
Passing subshell to bash function
我有一组 bash 日志函数,使我能够轻松地将所有输出重定向到日志文件并在发生某些事情时退出:
#! /usr/bin/env bash
# This script is meant to be sourced
export SCRIPT=[=11=]
if [ -z "${LOG_FILE}" ]; then
export LOG_FILE="./log.txt"
fi
#
# 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=""
if [ -n "" ]; then
IN=""
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}[=11=]')"
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 ""
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
。我知道两种分组方式:
子壳:它们不是用来传递的,自然是这样的:
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."
概括地说,我的问题是:有没有办法将命令组合(在我的例子中由 redirection/piping 组合)传递给 bash 函数?
按照它的设置方式,您只能传递 Posix 所谓的简单命令——命令名称和参数。子 shell 或大括号组等复合命令将不起作用。
但是,您可以在一个简单的命令中使用函数 运行 任意代码:
foo() { { echo "File content" > ~/user_file; } || fail "user_file could not be created."; }
log_wrap foo
您还可以考虑使用 exec
:
将包装器自动应用于脚本其余部分中的所有命令
exec > >(info) 2> >(error)
{ echo "File content" > ~/user_file; } || fail "user_file could not be created.";
我有一组 bash 日志函数,使我能够轻松地将所有输出重定向到日志文件并在发生某些事情时退出:
#! /usr/bin/env bash
# This script is meant to be sourced
export SCRIPT=[=11=]
if [ -z "${LOG_FILE}" ]; then
export LOG_FILE="./log.txt"
fi
#
# 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=""
if [ -n "" ]; then
IN=""
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}[=11=]')"
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 ""
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
。我知道两种分组方式:
子壳:它们不是用来传递的,自然是这样的:
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."
概括地说,我的问题是:有没有办法将命令组合(在我的例子中由 redirection/piping 组合)传递给 bash 函数?
按照它的设置方式,您只能传递 Posix 所谓的简单命令——命令名称和参数。子 shell 或大括号组等复合命令将不起作用。
但是,您可以在一个简单的命令中使用函数 运行 任意代码:
foo() { { echo "File content" > ~/user_file; } || fail "user_file could not be created."; }
log_wrap foo
您还可以考虑使用 exec
:
exec > >(info) 2> >(error)
{ echo "File content" > ~/user_file; } || fail "user_file could not be created.";