【问题标题】:ksh - pipe cannot write to outputksh - 管道无法写入输出
【发布时间】:2014-06-27 16:16:40
【问题描述】:

我在 AIX 6.1 下的 ksh(不是 ksh93)中使用这一行

# initiate earlier
LineStart=235559
cst_TracorTailLook=128
FileName=/LongPathWithSlash/logs/file.log
# /LongPathWithSlash/logs/file.log -> file_log.27Jun2014-00:00:00
# File is about 250.000 line and 60.000.000 bytes or more 

# the failing line
tail -n +$(( ${LineStart} - ${cst_TracorTailLook} + 1 )) ${FileName} |
    SomeAction

在直接会话中运行,没问题,它返回结果(在管道返回多行后用wc -l 测试)但是从代理(Tivoli 监控代理)运行返回:

tail: 0652-046 Cannot write to output.
There is no process to read data written to a pipe.

寻找限制我发现代理的限制(ulimit-a)比直接会话少

                     Direct      Agent
time(seconds)        unlimited   unlimited
file(blocks)         unlimited   unlimited
data(kbytes)         131072      unlimited
stack(kbytes)        32768       32768
memory(kbytes)       32768       32768
coredump(blocks)     2097151     unlimited
nofiles(descriptors) 2000        unlimited
threads(per process) unlimited   unlimited
processes(per user)  unlimited   unlimited

我在 AIX 5.3 上发现了几个关于 2 Gb 限制的问题,但这不是大小,也不是操作系统版本

最终,有没有不通过临时文件的替代方案?

【问题讨论】:

  • 经过大量分析,原因是由于文件在短时间内被修改和使用内存而导致文件上的管道“丢失”。更多的内存肯定会有所帮助,但不可能,解决方案是(不希望的)将信息提取到一个临时文件并从这个文件中工作

标签: pipe ksh tail


【解决方案1】:

当管道完成后的SomeAction在尾部完成之前完成时,您将有一个破碎的管道。 确保您的 SomeAction 将等到 tail 完成。

【讨论】:

  • 任何测试的操作都失败了(wc -l,一个简单的 sed,sum,...)
  • 管道可能被 Tivoli 破坏:link 指定代理部署工具必须完成任务的时间(以秒为单位)。如果工具未在 TIMEOUT 值指定的时间内完成任务,则终止任务。默认值为 600 秒。
  • 如何解决?您不希望代理在前一个脚本仍在运行时再次启动脚本。实际上,您希望代理执行一个简单的检查。您可以创建一个 crontab 条目,对您的日志文件执行 SomeAction 并在一个简单文件中报告它吗? Tivoli 不仅需要检查来自 crontab 的压缩结果文件。 (另一个问题是如何优化正在监视日志文件的脚本)
  • 重现错误信息:#!/bin/ksh TESTFILE="something" function testpipe { typeset -i count=1 maxcount=$1 print "Testing $maxcount output lines ..." while [ $count -le $maxcount ]; do echo $count >> ${TESTFILE} print "Output line $count" ((count+=1)) done | head -1 > /dev/null } testpipe 50000 2>&1 rm ${TESTFILE} 2>/dev/null
  • 链接断开,第一个程序仍在继续,管道后的命令刚刚放弃:我不确定超时是不是问题。我会发布另一个答案。
【解决方案2】:

确保代理调用的脚本在 10 秒内完成。 拖尾大型日志文件应在代理“外部”完成。 你说 crontab 在这里是不可能的,也许你可以启动一个后台进程:

LASTRESULT="cat ${ResultAction}"
nohup SomeAction > ${ResultAction} 2>&1 &

当然这样你的代理没有最新的结果,所以要注意经常启动代理。不太常见的是,您不希望并发(后台)进程扫描您的输出。 (在您当前的解决方案中也检查这一点)。

你能把你监控的日志文件变小吗?更频繁地关闭调试日志或轮换文件?写入日志文件的程序是否在每个日志操作后关闭文件描述符?

timestamp=${your_layout_yyyymmdd_hhmm}
mv ${FileName} ${FileName}.${timestamp}
touch ${FileName}
# I think Now you do not want to use a 
# tail -n +${offset} ${FileName}.${timestamp} | SomeAction
# and you are happy with
cat ${FileName}.${timestamp} | SomeAction

【讨论】:

  • tail 是在real 0m0.04s user 0m0.00s sys 0m0.00s中制作的,所以 10 秒是可以的。尾部只是上次检查的第 128 行的一部分 [提取最后一个非空行](仍然提供日志)并从提取的信息中处理文件。用于此的外部进程将过多地去同步。即使在相同的操作系统上使用更大的文件(不同的硬件),相同的脚本也可以在我们服务器的其余部分上运行。
  • 日志文件不是我自己的,我必须照原样接受它(没有复制,修改,...),而且在我的脚本期间通常仍然会提供它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多