- 背景**
我终于修复了我的问题,有stdout & stderr屏幕和一个文件,加上有一个单独的文件的错误。Output stdout and stderr to file and screen and stderr to file in a limited environment
- 问题**
问题在于行的顺序。
有时候是可以的:
FIRST
ERROR
LAST
ERROR2
LAST2
有时错误出现在末尾:
FIRST
LAST
LAST2
ERROR
ERROR2
我不知道为什么(除了下面可能有一个信号量...但是...不确定。如果是这样的话,除了给每个回显添加行号之外,没有解决方案)。
- 出现问题的代码部分**
{ "$0" "${mainArgs[@]}" 2>&1 1>&3 | tee -a "$logPath/$logFileName.err" 1>&3 ; } 3>&1 | tee -a "$logPath/$logFileName.log" &
- 完整的可测试代码**
m=0
declare -a mainArgs
if [ ! "$#" = "0" ]; then
for arg in "$@"; do
mainArgs[$m]=$arg
m=$(($m + 1))
done
fi
function containsElement()
# $1 string to find
# $2 array to search in
# return 0 if there is a match, otherwise 1
{
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
function hasMainArg()
# $1 string to find
# return 0 if there is a match, otherwise 1
{
local match="$1"
containsElement "$1" "${mainArgs[@]}"
return $?
}
function activateLogs()
# $1 = logOutput: What is the output for logs: SCREEN, DISK, BOTH. Default is DISK. Optional parameter.
{
local logOutput=$1
if [ "$logOutput" != "SCREEN" ] && [ "$logOutput" != "BOTH" ]; then
logOutput="DISK"
fi
if [ "$logOutput" = "SCREEN" ]; then
echo "Logs will only be output to screen"
return
fi
hasMainArg "--force-log"
local forceLog=$?
local isFileDescriptor3Exist=$(command 2>/dev/null >&3 && echo "Y")
if [ "$isFileDescriptor3Exist" = "Y" ]; then
echo "Logs are configured"
elif [ "$forceLog" = "1" ] && ([ ! -t 1 ] || [ ! -t 2 ]); then
# Use external file descriptor if they are set except if having "--force-log"
echo "Logs are configured externally"
else
echo "Relaunching with logs files"
local logPath="logs"
if [ ! -d $logPath ]; then mkdir $logPath; fi
local logFileName=$(basename "$0")"."$(date +%Y-%m-%d.%k-%M-%S)
exec 4<> "$logPath/$logFileName.log" # File descriptor created only to get the underlying file in any output option
if [ "$logOutput" = "DISK" ]; then
# FROM: https://stackoverflow.com/a/45426547/214898
exec 3<> "$logPath/$logFileName.log"
"$0" "${mainArgs[@]}" 2>&1 1>&3 | tee -a "$logPath/$logFileName.err" 1>&3 &
else
# FROM: https://stackoverflow.com/a/70790574/214898
{ "$0" "${mainArgs[@]}" 2>&1 1>&3 | tee -a "$logPath/$logFileName.err" 1>&3 ; } 3>&1 | tee -a "$logPath/$logFileName.log" &
fi
exit
fi
}
#activateLogs "DISK"
#activateLogs "SCREEN"
activateLogs "BOTH"
echo "FIRST"
echo "ERROR" >&2
echo "LAST"
echo "ERROR2" >&2
echo "LAST2"
1条答案
按热度按时间yzuktlbb1#
Stdout
1
和errout2
通过不同的文件描述符传递。如果非常忙碌,那么像这样非常接近的调用可能会混淆。您可以在调用之间使用
sleep 1
,这将给予系统有时间按顺序处理每个调用,但会降低脚本的速度。你可以睡不到一秒钟:例如
sleep 0.5
。