我有一个用 bash 编写的
debug()
函数,其目的是:
while ...; do ...; done < foo
/dev/stderr
或由
$DEBUG_LOG
指定的日志文件
# @description Write debug messages to $DEBUG_LOG if set, else /dev/stderr
# @usage debug <message>
function debug() {
if [[ "${DEBUG}" == "true" ]]; then
# Use $DEBUG_LOG if set, else /dev/stderr
local log_file="${DEBUG_LOG:-/dev/stderr}"
# Join all arguments using \n and prepend every line with "[debug] "
local debug_message=$(printf "%s\n" "${@}" | sed 's/^/[debug] /')
# Append the debug message to the log file
echo "${debug_message}" | dd of="${log_file}" conv=notrunc oflag=append status=none
fi
}
完整代码供好奇者
主要问题echo "${debug_message}" >> "${log_file}"
不是一个选择。它在场景 #2 上失败。当在
debug foo
循环内调用
while ... done < file.txt
时,在
debug()
函数内使用重定向将吃掉 STDIN 并中断循环。从那以后,我确定我需要一些命令,我可以用
pipe 代替并附加到日志文件或 STDERR,并且 dd
工作得很好,直到我尝试在 MacOS 上使用它😅 显然是 BSD 版本
dd
不允许
oflag=append
选项,这对于附加到日志文件相当重要...
append-stuff
,这样我就可以执行以下操作之一而无需重定向:
echo "${debug_message}" | append-stuff "${DEBUG_LOG:-/dev/stderr}"
append-stuff "${debug_message}" "${DEBUG_LOG:-/dev/stderr}"
debug_message=$'hello world\nsome |[]& weird ch4r4ct3r$!\nfoo bar'
sed
sed -e '$a '"${debug_message}" "${DEBUG_LOG:-/dev/stderr}"
# sed: -e expression #1, char 42: unterminated `s' command
sed -e '$a helloworld' /dev/stderr
# hangs
echo "${debug_message}" | sed -e '$r /dev/stdin' "${DEBUG_LOG:-/dev/stderr}"
# hangs
awk -i 就地echo "${debug_message}" | awk -i inplace ... /dev/stdin ... /dev/stderr
的几种不同变体,但它们要么打印警告,要么挂起外壳。更重要的是,就地扩展似乎不是内置/便携式的。dd
echo "${debug_message}" \
| dd of="${DEBUG_LOG:-/dev/stderr}" conv=notrunc oflag=append status=none
# works, but oflag=append is not available on MacOS, and there doesn't seem
# to be an equivalent flag in the BSD version of dd
append-stuff
类型的命令,就像我正在寻找的那样,它要么内置于 bash,要么是人们可以合理地期望在任何机器上找到的 *nix 工具标准套件的一部分,但是如果这里有人知道这样的事情,我将非常感激😄
#! /bin/bash
# @description Write debug messages to $DEBUG_LOG if set, else /dev/stderr
# @usage debug <message>
function debug() {
if [[ "${DEBUG}" == "true" ]]; then
# Use $DEBUG_LOG if set, else /dev/stderr
local log_file="${DEBUG_LOG:-/dev/stderr}"
# Join all arguments using \n and prepend every line with "[debug] "
local debug_message=$(printf "%s\n" "${@}" | sed 's/^/[debug] /')
# Append the debug message to the log file
#echo "${debug_message}" | dd of="${log_file}" conv=notrunc oflag=append status=none
echo "${debug_message}" >> "${log_file}"
fi
}
DEBUG=true
DEBUG_LOG=$(mktemp)
yes | head -5 > foo
i=5
while (( i > 0 )); do
debug "$i"
read f
printf '%s\n' "$f"
(( i-- ))
done < foo
cat "$DEBUG_LOG"
rm "$DEBUG_LOG"
您将看到调试消息
[debug] 5
[debug] 4
[debug] 3
[debug] 2
[debug] 1
打印。