如何完整记录所有bash脚本操作?


44

我想从脚本输出中捕获所有带有错误消息的日志数据,并将它们全部重定向到日志文件。

我有如下脚本:

#!/bin/bash
(
echo " `date` : part 1 - start "
ssh -f admin@server.com 'bash /www/htdocs/server.com/scripts/part1.sh logout exit'
echo " `date` : sleep 120"
sleep 120
echo " `date` : part 2 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part2.sh logout exit'
echo " `date` : part 3 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part3.sh logout exit'
echo " `date` : END"
) | tee -a /home/scripts/cron/logs

我想查看文件中的所有操作 /home/scripts/cron/logs

但是我只看到我在echo命令之后输入的内容。

SSH命令是否登录成功?

我需要收集所有日志数据。我需要它来监视脚本中每个命令的结果,以更好地分析脚本失败时正在发生的事情。


您也可以使用“脚本”执行此操作。看到这个帖子:[点击这里] [1] [1]:stackoverflow.com/questions/5985060/...
xX0v0Xx

您必须谨慎使用errexit-我注意到它被忽略,或者错误未退出脚本。如果脚本中包含以下内容:command || 命令失败时的dosmthg脚本不会立即在设置errexit的情况下退出,而是运行dosmthg并继续执行脚本

Answers:


66

我通常在每个脚本的开头放置类似于以下内容的内容(特别是如果它将作为守护程序运行):

#!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2>&1
# Everything below will go to the file 'log.out':

说明:

  1. exec 3>&1 4>&2

    保存文件描述符,以便可以将它们恢复到重定向之前的状态,也可以将自身用于输出到以下重定向之前的状态。

  2. trap 'exec 2>&4 1>&3' 0 1 2 3

    恢复特定信号的文件描述符。通常不需要,因为应该在子外壳退出时将其还原。

  3. exec 1>log.out 2>&1

    重定向stdout到文件,log.out然后重定向stderrstdout。请注意,当您希望它们转到同一文件时,顺序很重要。stdout 必须先重定向,然后才能stderr重定向到stdout

从那时起,要查看控制台上的输出(也许),您只需将其重定向到即可&3。例如,

echo "$(date) : part 1 - start" >&3

stdout在执行上面的第3行之前,它将转到所指示的任何地方(大概是控制台)。


<< niceroot,谢谢!我在脚本的开头添加了三行(exec,trap,exec),并且能够同时获取stdout和stderr。但是一个问题:我已经看到“文件描述符3(pipe:XXX)在some_command上泄漏” ...请让我知道如何避免出现这些错误。我在自定义面板中使用基于busybox的sh。
kumar

3
伟大的功夫在这里!-更好的是使用trap 'exec 2>&4 1>&3' 0 1 2 3 RETURN。每次使用.shell执行shell函数或脚本时,RETURN伪sigspec恢复文件描述符。或源内置命令执行完毕。由于这个原因(以及其他原因),我在最后两行中添加:returnexit 0-仅需2美分,@ nicerobot恭喜您!
DavAlPi'3

通过shell的全局变量记录shell脚本的细节很多。我们可以在外壳程序脚本中模拟类似的日志记录:cubicrace.com/2016/03/efficiency-logging-mechnism-in-shell.html 文章详细介绍了日志级别,如INFO,DEBUG,ERROR。跟踪详细信息,例如脚本入口,脚本出口,函数入口,函数出口。
Piyush Chordia'3

trap信号的枚举看起来有些奇怪。通常,您也希望包括在内15
三胞胎


14

要将ssh输出输出到您的日志文件,您必须重定向stderrstdout。您可以通过2>&1在bash脚本之后追加来做到这一点。

它应该看起来像这样:

#!/bin/bash
(
...
) 2>&1 | tee ...

当这不能按正确的顺序显示消息时,请尝试添加另一个子shell:

#!/bin/bash
((
...
) 2>&1) | tee ...

1
这很好。实际上,您可以使用以下命令来指示stdout和stderr:( ... ) |& tee output.log
Noam Manos

13

当我读到您的问题时,您不想记录输出,但是整个命令序列(在这种情况下,其他答案)对您没有帮助。

使用-x调用shell脚本以输出所有内容:

sh -x foo.sh

登录到所需的文件:

sh -x foo.sh >> /home/scripts/cron/logs


2
为-x选项+1
Coc 2013年

10

在bash中,您可以放下set -x它,并且它将在执行之后打印出它执行的每个命令(以及bash变量)。您可以使用关闭它set +x

如果您想变得偏执,可以set -o errexit输入脚本。这意味着,如果一个命令返回了非零的退出代码,则脚本将失败并停止,这是Unix表示发生问题的标准方法。

如果你想获得更好的日志,你应该看看tsmoreutils是Debian / Ubuntu的软件包。它将为每行加上时间戳作为前缀并打印出来。这样您就可以看到事情发生的时间。


1
“ set -o errexit”必须与“ set -e”相同
Ajith Antony

0

遵循别人的说法,手册是一个很好的资源。我放:

#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x

在脚本顶部,我希望继续进行操作,或者set -ex如果出现错误应退出脚本。


这对ssh日志和成功执行命令有什么帮助?
asktyagi

使用OP的伪脚本进行测试,它会记录每个命令以及任何结果:ssh超时,不正确的域等。或者对于有效的ssh地址,它将命令记录在远程shell中。如果需要有关ssh登录的更多信息,也许ssh -vv
dragon951
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.