管道中的bash脚本如何检测到它';的数据源已死亡。?
我在一台没有logrorate的旧机器上工作 [实际上,它有busybox 0.6,这在大多数情况下是“形式无效的”。] 我有openvpn运行,我希望能够看到它一直在做什么。我正在使用的openvpn可以将进度信息输出到标准输出或命名日志文件 我试图找到一种方法来停止使用一个日志文件,并在另一个日志文件上启动它,但失败了。也许某个SIGUSR或其他东西会使它关闭并重新打开输出文件,但我找不到它 所以我编写了一个脚本,它读取stdin,并将输出定向到一个旋转日志文件 所以现在我需要做的就是将openvpn的输出通过管道传输到它 工作完成了 除了如果我杀死openvpn,处理其输出的脚本将永远运行。它已经无能为力了,所以我希望它自动死亡 有没有办法在脚本“EOF on STDIN”或使用“find the process ID which being my STDIN”之类的东西中捕获这种情况管道中的bash脚本如何检测到它';的数据源已死亡。?,bash,Bash,我在一台没有logrorate的旧机器上工作 [实际上,它有busybox 0.6,这在大多数情况下是“形式无效的”。] 我有openvpn运行,我希望能够看到它一直在做什么。我正在使用的openvpn可以将进度信息输出到标准输出或命名日志文件 我试图找到一种方法来停止使用一个日志文件,并在另一个日志文件上启动它,但失败了。也许某个SIGUSR或其他东西会使它关闭并重新打开输出文件,但我找不到它 所以我编写了一个脚本,它读取stdin,并将输出定向到一个旋转日志文件 所以现在我需要做的就是将op
我明白这与问题相似 但这并不完全是因为我无法控制openvpn的行为(除非我可以杀死它)。我确实可以控制接收openvpn输出的脚本,但无法确定如何检测openvpn的死亡或从它到我的管道 我的上层脚本大致如下:
vpn_command="openvpn --writepid ${sole_vpn_pid_file} \
--config /etc/openvpn/openvpn.conf \
--remote ${VPN_HOST} ${VPN_PORT} "
# collapse sequences of multiple spaces to one space
vpn_command_tight=$(echo -e ${vpn_command}) # must not quote the parameter
# We pass the pid file over explicitly in case we ever want to use multiple VPNs.
( ./${launchAndWaitScriptFullName} "${vpn_command_tight}" "${sole_vpn_pid_file}" 2>&1 | \
./vpn-log-rotate.sh 10000 /var/log/openvpn/openvpn.log ) &
如果我终止openvpn进程,“vpn log rotate.sh”进程将保持运行
即:
#!/bin/sh
# @file vpn-log-rotate.sh
#
# @brief rotates stdin out to 2 levels of log files
#
# @param linesPerFile Number of lines to be placed in each log file.
# @param logFile Name of the primary log file.
#
# Archives the last log files on entry to .last files, then starts clean.
#
# @FIXME DGC 28-Nov-2014
# Note that this script does not die if the previous stage of the pipeline dies.
# It is possible that use of "trap SIGPIPE" or similar might fix that.
#
# @copyright Copyright Dexdyne Ltd 2014. All rights reserved.
#
# @author DGC
linesPerFile="$1"
logFile="$2"
# The location of this script as an absolute path. ( e.g. /home/Scripts )
scriptHomePathAndDirName="$(dirname "$(readlink -f $0)")"
# The name of this script
scriptName="$( basename $0 )"
. ${scriptHomePathAndDirName}/vpn-common.inc.sh
# Includes /sbin/script_start.inc.sh
# Reads config file
# Sets up vpn_temp_directory
# Sets up functions to obtain process id, and check if process is running.
# includes vpn-script-macros
# Remember our PID, to make it easier for a supervisor script to locate and kill us.
echo $$ > ${vpn_log_rotate_pid_file}
onExit()
{
echo "vpn-log-rotate.sh is exiting now"
rm -f ${vpn_log_rotate_pid_file}
}
trap "( onExit )" EXIT
logFileRotate1="${logFile}.1"
# Currently remember the 2 previous logs, in a rather knife-and-fork manner.
logFileMinus1="${logfile}.minus1"
logFileMinus2="${logfile}.minus2"
logFileRotate1Minus1="${logFileRotate1}.minus1"
logFileRotate1Minus2="${logFileRotate1}.minus2"
# The primary log file exist, rename it to be the rotated version.
rotateLogs()
{
if [ -f "${logFile}" ]
then
mv -f "${logFile}" "${logFileRotate1}"
fi
}
# The log files exist, rename them to be the archived copies.
archiveLogs()
{
if [ -f "${logFileMinus1}" ]
then
mv -f "${logFileMinus1}" "${logFileMinus2}"
fi
if [ -f "${logFile}" ]
then
mv -f "${logFile}" "${logFileMinus1}"
fi
if [ -f "${logFileRotate1Minus1}" ]
then
mv -f "${logFileRotate1Minus1}" "${logFileRotate1Minus2}"
fi
if [ -f "${logFileRotate1}" ]
then
mv -f "${logFileRotate1}" "${logFileRotate1Minus1}"
fi
}
archiveLogs
rm -f "${LogFile}"
rm -f "${logFileRotate1}"
while true
do
lines=0
while [ ${lines} -lt ${linesPerFile} ]
do
read line
lines=$(( ${lines} + 1 ))
#echo $lines
echo ${line} >> ${logFile}
done
mv -f "${logFile}" "${logFileRotate1}"
done
exit_0
更改此项:
read line
echo ${line} >> ${logFile}
为此:
read line || exit
printf %s "$line" >> "$logFile"
因此,如果读取失败(因为您已达到EOF),您将退出
更好的是,将其更改为:
IFS= read -r line || exit
这样就不会丢弃前导空格,也不会将反斜杠视为特殊字符
当你这样做的时候,一定要改变这一点:
read line
echo ${line} >> ${logFile}
为此:
read line || exit
printf %s "$line" >> "$logFile"
这样,如果
$line
有一个前导-
,或者包含*
或?
或诸如此类的内容,您就不会遇到问题。您能发布脚本吗?