You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何stdout不是TTY但stderr却为TTY?

为何stdout不是TTY但stderr却为TTY?

这问题挺典型的,咱们结合你给出的测试结果来拆解原因:

先还原你的测试场景和输出(修正了转义引号,方便阅读):

$ php -r 'var_dump(exec("test -t 1 && echo y"));'
string(0) ""
$ php -r 'var_dump(system("test -t 1 && echo y"));'
string(0) ""
$ php -r 'var_dump(passthru("test -t 1 && echo y"));'
NULL
$ php -r 'var_dump(exec("test -t 2 && echo y"));'
string(1) "y"
$ php -r 'var_dump(system("test -t 2 && echo y"));'
y
string(1) "y"
$ php -r 'var_dump(passthru("test -t 2 && echo y"));'
y
NULL
$ php -v
PHP 8.2.20 (cli) (built: Jul  4 2024 02:23:40) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.20, Copyright (c) Zend Technologies
$ uname -rsm
FreeBSD 13.3-RELEASE-p1 amd64

核心原因在于PHP的exec、system、passthru这几个执行外部命令的函数,对stdout和stderr的处理逻辑完全不同:

  • 对于stdout(文件描述符1):这些函数默认会捕获外部命令的stdout输出——要么把结果返回给PHP代码(比如exec),要么转输出到PHP自身的stdout(比如system、passthru)。但不管哪种方式,外部命令的stdout都没有直接连接到终端TTY,而是连到了PHP进程的管道或缓冲区,所以test -t 1会判断为非TTY,自然不会输出"y"。
  • 对于stderr(文件描述符2):默认情况下PHP不会捕获stderr,外部命令的stderr会直接继承PHP进程的stderr——也就是你当前正在使用的终端,所以test -t 2会判断为TTY,输出"y"。

如果想让外部命令的stdout也成为TTY,可以用proc_open函数手动指定终端作为标准输出,不过日常用exec这类函数时,这种stdout被捕获/重定向的行为是PHP的默认设计。

备注:内容来源于stack exchange,提问作者Rihad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 12:43:03