如何让Linux上的SCP输出“成功”stdout而不是stderr?

我们有一个cron工作,使用SCP将资料发送给另一家公司。 该命令如下所示:

10 0 * * * ssh USER@LOCAL-SERVER 'scp -q ~/some/dir/* REMOTE_SERVER:/other/dir/' >> ~/log/some.log 

这是由其他人设置的。 现在我的问题是,我的老板是在cron邮件列表中,尽pipe“〜〜/ log / some.log”每天仍然发送一封电子邮件,因为即使转移成功,它仍然输出:

 Connection to REMOTE_SERVER 12345 port [tcp/*] succeeded! 

除非发生错误,否则我的老板不想收到这封电子邮件。

这个命令真的在一个脚本里面,我忽略了这个问题使得问题变得简单。 它运行在RHEL 6服务器上。 但是因为这是我们与REMOTE_SERVER交谈的唯一线路,所以它必须来自那里。 而我们在LOCAL-SERVER(Ubuntu 10.04.4 LTS)上执行命令的原因是因为我们在数据库服务器上,它不能通过防火墙,所以我们首先将数据复制到另一台本地服务器,并从那里上传。

当没有使用-q时,我也会得到以下输出:

 SSH Server supporting SFTP and SCP 

我不想redirect所有的stderr输出,因为我仍然想在发生错误时收到邮件。

我不认为你可以有select地redirectSTDERR输出,而不用重写程序来写这些特定的消息到STDOUT而不是STDERR 。 但是,你可以做的是编写一个包装脚本来过滤不需要的消息,并在cron作业中运行该脚本。

 #!/bin/bash (ssh USER@LOCAL-SERVER ... 3>&1 1>&2- 2>&3-) 2>> ~/log/some.log \ | grep -v "Connection .* succeeded" 1>&2 exit $? 

出于好奇,为什么不直接在LOCAL-SERVER上用scp命令运行cron作业?

编辑:你想过滤出一些STDERR输出,同时将所有STDOUT输出redirect到一个文件,但是pipe道可以将一个进程的STDOUT连接到另一个进程的STDIN|&2>&1 | 将不起作用,因为STDOUT已经被redirect到~/log/some.log ,所以没有任何东西进入pipe道,并且在你的日志文件中有很多不需要的输出。

但是,可以交换描述符,这样STDOUT实际上转到了STDERRSTDERR实际上转到了STDOUT 。 然后,您可以将所有STDERR输出redirect到您的日志文件,并通过grep过滤STDOUT输出。 有人在stackoverflow发布这个巧妙的小技巧。 1>&2将过滤的输出返回到STDERR

假设你正在使用BASH:

首先进行复制,交换stdout和stderr:

2>&1 >>〜/ log / some.log ssh USER @ LOCAL-SERVER'scp -q〜/ some / dir / * REMOTE_SERVER:/ other / dir /'

然后你build立一个pipe道来抓取任何正在stderr的东西:

2>&1 >>〜/ log / some.log ssh USER @ LOCAL-SERVER'scp -q〜/ some / dir / * REMOTE_SERVER:/ other / dir /'|

而grep只为失败的消息:

2>&1 >>〜/ log / some.log ssh USER @ LOCAL-SERVER'scp -q〜/ some / dir / * REMOTE_SERVER:/ other / dir /'| grep -E“失败消息”

这将产生cron抓取并包含在其MAIL消息中的输出。 所有其他“stderr”输出将消失(丢失)。 如果由于某种原因,您想保存所有stderr的副本,请先使用tee命令:

2>&1 >>〜/ log / some.log ssh USER @ LOCAL-SERVER'scp -q〜/ some / dir / * REMOTE_SERVER:/ other / dir /'| tee -a〜/ log / some_other.log | grep -E“失败消息”

将所有stderr的副本放入新的日志文件,然后只有失败消息才会进入CRON邮件。