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

如何用C++实现tmux多窗格的输入输出交互及消息转发?

Tmux多窗格交互功能实现问题

下方代码用于在tmux中创建两个窗格,并执行倒计时至20的逻辑:

#include <iostream>
#include <fstream>
#include <thread>
#include <vector>
#include <chrono>
#include <atomic>
#include <mutex>
#include <string>
#include <array>
#include <memory>

// 执行shell命令并返回结果
std::string exec(const std::string& cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
    if (!pipe) {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
        result += buffer.data();
    }
    return result;
}

// 线程执行函数
void threadFunction(const std::string& tty, std::atomic<bool>& running, int threadId) {
    int messageCount = 0;
    std::ofstream ttyStream(tty);
    if (!ttyStream.is_open()) {
        std::cerr << "Failed to open tty: " << tty << std::endl;
        return;
    }
    while (running.load()) {
        ttyStream << "Thread " << threadId << " is running: message " << messageCount++ << std::endl;
        ttyStream.flush();
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

void kill(const std::string& sessionName){
    std::string command = "tmux send-keys -t " + sessionName + " \" tmux kill-server\" Enter";

    // 捕获输出用于调试
    std::string output = exec(command);
    std::cerr << "Command output: " << output << std::endl;

    if (std::system(command.c_str()) != 0) {
        std::cerr << "Error executing command: " << command << std::endl;
    }
}

int main() {
    const std::string sessionName = "Client";
    const int numThreads = 2; // 线程与窗格数量

    // 创建tmux会话和窗格,并获取它们的TTY
    std::string createSessionCmd = "tmux new-session -d -s " + sessionName + " -PF '#{pane_id}' 'tail -f /dev/null'";
    std::string pane1 = exec(createSessionCmd);
    pane1.pop_back(); // 移除换行符

    std::string splitPaneCmd = "tmux split-window -t " + sessionName + " -PF '#{pane_id}' 'tail -f /dev/null'";
    std::string pane2 = exec(splitPaneCmd);
    pane2.pop_back(); // 移除换行符

    std::string getTtyCmd1 = "tmux display-message -p -t " + pane1 + " '#{pane_tty}'";
    std::string tty1 = exec(getTtyCmd1);
    tty1.pop_back(); // 移除换行符

    std::string getTtyCmd2 = "tmux display-message -p -t " + pane2 + " '#{pane_tty}'";
    std::string tty2 = exec(getTtyCmd2);
    tty2.pop_back(); // 移除换行符

    std::cout << "TTY1: " << tty1 << std::endl;
    std::cout << "TTY2: " << tty2 << std::endl;

    std::atomic<bool> running(true);

    // 创建并运行线程
    std::thread t1(threadFunction, tty1, std::ref(running), 1);
    std::thread t2(threadFunction, tty2, std::ref(running), 2);
    
    std::thread t3([&sessionName]() {
        std::this_thread::sleep_for(std::chrono::seconds(20)); // 延长测试休眠时间
    
        std::string command = "tmux new-window -t " + sessionName + " -n thread" + std::to_string(2);
        std::system(command.c_str());
        kill(sessionName);

    });

    t1.detach();
    t2.detach();
    t3.detach();

    // 附加到tmux会话
    std::string cmd = "tmux attach -t " + sessionName;
    std::system(cmd.c_str());

    return 0;
}

当前问题与期望效果

  • 现有代码问题:窗格无法接收任何输入,甚至无法执行命令,关闭tmux会话必须新建窗口执行tmux kill-server。
  • 期望实现:
    1. 线程在指定窗格显示计数消息
    2. 用户在某窗格输入内容时,计数暂停
    3. 输入内容转发至另一窗格显示
    4. 输入完成后从暂停位置继续计数

替代方案的问题

若不直接操作TTY,尝试让每个窗格将用户输入写入文件,再通过新线程读取内容并显示到指定窗格,但会出现两个问题:

  • 用户输入回车后,系统会提示输入内容不是有效命令
  • C++程序需通过echo命令显示消息,导致消息重复显示(如下图):

不使用TTY仅通过C++创建tmux窗格的效果

内容的提问来源于stack exchange,提问作者Karan Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:58:16