【问题标题】:Tricky stderr redirection with s3cmd使用 s3cmd 进行棘手的 stderr 重定向
【发布时间】:2012-07-03 12:58:11
【问题描述】:

我有一些奇怪的行为从 s3cmd 重定向标准输出和标准错误。例如:

$ touch test

$ s3cmd put test s3://non_existent_bucket
test -> s3://non_existent_bucket/test  [1 of 1]
 4 of 4   100% in    0s    88.17 B/s  done
ERROR: S3 error: 404 (NoSuchBucket): The specified bucket does not exist

这个输出是(如果我没有弄错的话)部分标准输出和部分标准错误。如下所示:

$ s3cmd put test s3://non_existent_bucket 2> log
test -> s3://non_existent_bucket/test  [1 of 1]
 4 of 4   100% in    0s   120.11 B/s  done

$ cat log
ERROR: S3 error: 404 (NoSuchBucket): The specified bucket does not exist

实际上,stderr 被重定向,但我们需要 stdout 和 stderr。让我们先试试标准输出:

$ s3cmd put test s3://non_existent_bucket > log
ERROR: S3 error: 404 (NoSuchBucket): The specified bucket does not exist

$ cat log

它不是在命令之后写的,所以我理解 stdout 实际上是重定向(或其他东西),但它不会被日志文件捕获。我猜它会以某种方式检测它是否连接到 tty,并且只在第一种情况下输出这种数据。

以同样的方式,如果我尝试重定向两个流,我会得到 stderr 但不是我需要的 stdout 输出:

$ s3cmd put test s3://non_existent_bucket >& log

$ cat log
ERROR: S3 error: 404 (NoSuchBucket): The specified bucket does not exist

事实上,我需要做的是从 PHP 调用它并获得完整的输出。我只找到了执行命令和检索标准输出的方法,所以我这样做如下:

exec('s3cmd put test s3://non_existent_bucket 2>&1', $output);

在这里,我没有从任何一个流中得到任何输出。我想我丢失了标准输出,因为 s3cmd 检测到它没有连接到 tty,但是标准错误我仍然不明白为什么它没有被捕获。

尝试使用 popen() 和 exec() 得到相同的结果。

我需要整个输出,或者至少是标准输出(尽管我猜进度信息会以某种方式被抓取)。有什么想法吗?

提前致谢!!

【问题讨论】:

  • 您是否尝试过proc_open() 提供的更复杂但更细粒度的控件?
  • 我没有,但现在我做到了,如果我没有做错什么,问题是一样的:s

标签: php bash shell s3cmd


【解决方案1】:

man page for s3cmd 详细说明了 --progress/--no-progress 标志,描述如下:

显示或不显示进度表。在 TTY(例如控制台或 xterm)上运行时,默认显示进度表。如果不在 TTY 上(例如,输出重定向到某处或从 cron 运行),则默认不显示进度表。

所以看起来 s3cmd 会执行类似 isatty(0) 的操作来确定是否将进度详细信息写入 STDOUT,但如果您明确指定 --[no-]progress,它将强制执行一种或另一种行为。

试试:

exec('s3cmd --progress put test s3://non_existent_bucket 2>&1', $output);

【讨论】:

  • 好的!这有效:) 我在文档中完全忽略了这一点。非常感谢!但我仍然想得到 stderr 。稍后我会将您的答案标记为已接受,以查看是否有人(甚至您)帮助我。 PD:管理员:可以将两个答案标记为已接受吗?
  • 那也没有得到 STDERR 吗?我原以为2>&1 应该得到它。很奇怪——它有点暗示没有任何东西被写入 STDERR。如果您 exec() 成功将 STDERR 记录到文件的命令怎么办 - 文件是否仍然捕获错误消息?即exec('s3cmd put test s3://non_existent_bucket 2> log'); 还要验证test 是否存在于您的 PHP 脚本的工作目录中(尽管如果不是,我会这样做虽然这也会引发 STDERR 消息)。
  • 啊!不,我错了,我再次对其进行了测试,实际上它获取了所有输出。非常感谢 DaveRandom!
猜你喜欢
  • 1970-01-01
  • 2014-12-07
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多