cout << std::flush会让我的println(..) 在Docker日志中被刷新。我尝试了两种替代方法:setvbuf和 cout << std::unitbuf,但都没有成功。

前端开发 2026-07-07

我的C++程序在一个 docker-compose 里面运行。
只要在它们之后执行一个 cout << std::flush,我就可以把它的 println 调用输出到Docker日志中:

println("Hello! I'm tempete C++ module, starting...");
cout << std::flush;

否则,我的程序的 stdout 不会被刷新。这个方法可行,但很繁琐。

为了避免这种情况,在程序开头我尝试了以下这些语句(在不同的执行中)。但都没有效果。

cout << std::unitbuf;

或者

setvbuf(stdout, NULL, _IONBF, 0);

有什么单一的函数调用 / 语句,能够让我要在每次 println 之后都不再执行 cout << std::flush 吗?


如果你尝试这个简单的程序:

#include <print>

int main(int argc, char* argv[]) {
    println("Hello! I'm tempete C++ module, starting...");
    while(true);
    return 0;
}

然后在与其他语言编写的程序一起运行一个 docker compose up | grep Hello,你会看到:

galerne-beaufort  | Hello! I'm galerne Rust module, starting...
brise-beaufort    | 06:46:53.216 [main] INFO fr.beaufort.brise.application.BriseApplication -- Hello! I'm brise Java module, starting...
orchestrator-beaufort  | 06:46:53.268 [main] INFO fr.beaufort.orchestrator.application.OrchestratorApplication -- Hello! I'm orchestrator Java module, starting...
ponant-beaufort        | Hello! I'm ponant Typescript module, starting...

Java由 Logger Log4j、TypeScript通过 console.log(...)、Rust通过 println(...) 宏,它们都能够输出到Docker日志,但仅凭C++及其 println(...) 自己则不行。

如果你在C++的 println 之后再加一个 std::cout << std::flush;,你就会看到这条消息。

tempete-beaufort  | Hello! I'm tempete C++ module, starting...
galerne-beaufort  | Hello! I'm galerne Rust module, starting...
brise-beaufort    | 06:48:19.873 [main] INFO fr.beaufort.brise.application.BriseApplication -- Hello! I'm brise Java module, starting...
orchestrator-beaufort  | 06:48:19.904 [main] INFO fr.beaufort.orchestrator.application.OrchestratorApplication -- Hello! I'm orchestrator Java module, starting...
ponant-beaufort        | Hello! I'm ponant Typescript module, starting...

所以,在我的想法里,这不是Docker的问题,而是C++的一个怪异之处,因为 println(...),按它的名字来看,应该写入一个 \n(它确实会写入),这在某种程度上应该会自动引发一次刷新。

但如果 std::coutstdout 并非真正统一,这可能就能解释清楚。

解决方案

@Someprogrammerdude led me to the solution:

In docker-compose.yaml ask the container to act as a tty, by a tty: true.

  tempete:
    build:
      context: apps/tempete
      dockerfile: Dockerfile
    container_name: tempete-beaufort
    tty: true
    environment:
      - KAFKA_BOOTSTRAP_SERVERS_CONFIG=kafka:9092
    depends_on:
      kafka:
        condition: service_healthy

这解决了问题,并避免了手动刷新。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章