【问题标题】:How to track bash script - exit status and why it failed如何跟踪 bash 脚本 - 退出状态及其失败的原因
【发布时间】:2013-10-19 17:54:30
【问题描述】:

有时我需要像这样运行命令:

cat file.txt | awk ' NR%4 == 2 { print $1 }' | sort | uniq -c | sort -gr >>output.txt &

超过大文件(2-32 GB 大小)。我在晚上启动命令,当我早上来的时候,output.txt 有时是空的,并且进程不再运行。

请问,我如何追踪正在发生的事情?为什么以及何时我的命令失败了?我知道管道正在工作,因为有时它会成功完成。

非常感谢!

更新: 我现在认为我的进程已被终止,因为我运行此计算时的服务器建议仅用于交互式使用。如果这是真的,我只能从日志文件中看到它没有成功 - 还没有完成。

有什么方法可以查出我的进程实际上被杀死了?谢谢。

【问题讨论】:

  • 如果猫让你的一天更容易理解,请保留它们。

标签: bash exitstatus


【解决方案1】:

第一步,将该脚本封装在一个文件中,而不是直接在终端上运行它(这样我们就会失去 UUOC 奖)。

#!/bin/bash

{
awk 'NR%4 == 2 { print $1 }' file.txt | sort | uniq -c | sort -gr >>output.txt
} 2>error.log

这将捕获文件error.log 中的所有错误消息。然后您可以添加诊断信息。

#!/bin/bash

{
date >&2
set -x
awk 'NR%4 == 2 { print $1 }' file.txt | sort | uniq -c | sort -gr >>output.txt
date >&2
} 2>error.log

现在您已经获得了时间信息 — 何时开始和何时结束。由于您在bash,如果您愿意,您可以安排捕获管道中每个进程的退出状态,这样您就可以确切地知道哪些命令以哪种状态退出。您可能会或可能不会收到有关哪个进程被杀死的消息(如果一个进程被外部信号杀死),但如果该进程自行终止,它应该在标准错误上打印一条消息(这就是它的用途,以及为什么将错误打印到标准错误而不是标准输出至关重要)。

使用此脚本,您可以将标准输出发送到output.txt,将标准错误发送到error.log;该脚本不使用标准输入(数据来自file.txt)。因此,您可以使用 nohup 运行此程序,也可以使用 & 在后台运行,而不会有任何疑虑。

您可能更愿意将名称file.txt 设置为命令行参数;您可能希望使输出和日志文件可配置。您可能更喜欢日期输出的不同格式。所有这些都是可以调整的。但关键是把它放到一个shell脚本中,这样你就可以直接系统地处理这些事情了。

【讨论】:

  • 谢谢,将它放入这样的脚本中绝对是个好主意。与@damienfrancois 结合使用时,建议可能会变得非常强大。谢谢你们!
  • @Perlnika 要捕获管道中每个命令的退出状态,请使用 PIPESTATUS bash 变量。
【解决方案2】:

使用screenpvtee 来捕获所有错误,有一个进度条,并允许从最后一个成功的命令重新启动,而不是在出现错误时从头开始。

您可以使用screenmultiplexer)而不是后台处理您的进程。这样,您可以随时查看其状态,而不会错过错误消息。只需输入screen,在没有& 的情况下运行您的命令,然后点击CTRL-a,d。然后,您可以注销。要稍后查看输出,请登录(甚至是远程登录)并输入 screen -r

此外,如果您将最初的 cat 替换为 pvPipe Viewer),您将看到一个进度条告诉您已经处理了多少:

pv -cN file.txt

你会看到类似

的东西
611MB 0:00:11 [58.3MB/s] [=>      ] 15% ETA 0:00:59

每当您重新附加 screen 进程时。

或者/互补地,您可以在命令之后插入tee,以在将其输出复制到文件之前将其传播到下一个文件。

uniq -c | tee afteruniq.tmpfile | sort -gr

文件afteruniq.tmpfile 将包含uniq -c 的结果。所以你知道什么有效,什么失败了。您还可以在 tee'd 文件的最后一个成功步骤之后恢复链。

【讨论】:

  • 不是 100% 你的问题,但script 有时也很方便。我有时将它与screen 一起使用。
【解决方案3】:

您需要将stderrstdout 都重定向到您的输出文件。

让你的命令像这样:

( awk 'NR%4 == 2{print $1}' file.txt| sort | uniq -c | sort -gr ) >> output.txt 2>&1 &

记下2>&1stderr 重定向到stdout 要去的任何地方。

【讨论】:

  • 谢谢。如果我的进程被杀死,我还会发现一些消息吗?因为在这个管道中 output.txt 通常是空的,除非它运行到最后。
  • 现在将捕获output.txt中的所有stdout和stderr。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
  • 2019-08-29
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多