【问题标题】:How to output to the currently visible terminal如何输出到当前可见的终端
【发布时间】:2015-02-24 09:43:09
【问题描述】:

我想输出一些文本作为对信号SIGUSR1的响应

即用户将kill -USR1 <pid> 发送到在后台或另一个终端中启动的进程。

我想在调用kill 的终端中获得一些输出。

我怎样才能做到这一点?

【问题讨论】:

  • serverfault.com/a/94995 可能是一个不错的起点。然后你可以查看/proc/<pid>/fd/1,看看它在哪里发送控制台输出。
  • 确实是一个很好的起点:)
  • 实际上你不知道信号来自哪个终端:它可能是从不同的shell发出的。如果只有一个终端/窗口需要考虑,您可以写入 /dev/tty
  • @HeikoSchäfer 我没有时间尝试任何东西,而且看起来没有人知道一个明显的答案,所以如果您确实从该链接(或其他任何内容)中做出任何有用的事情,请不要犹豫,发布您自己问题的答案。
  • @BoBTFish 非常感谢,成功了 :)

标签: c++ c linux tty


【解决方案1】:

@BoBTFish 的评论有效。一个可能的伪 C++ 实现:

// somewhere in code:
std::memset(&sa, 0, sizeof(struct sigaction));
sa.sa_sigaction = sh_dump;
sa.sa_flags = static_cast<int>(SA_SIGINFO); // <- important, else you'll get an invalid siginfo_t pointer
sigaction(SIGUSR1, &sa, NULL);

void sh_dump(int, siginfo_t *info, void *) {

    if(info) {

        // do some locking of your choice

        char *p = NULL;
        char sp[PATH_MAX] = "";

        std::snprintf(sp, PATH_MAX, "/proc/%d/stat", info->si_pid);

        int tty_nr = 0;
        FILE *spf;

        if((spf = std::fopen(sp, "r"))) {

            int iDummy;
            char cDummy, *sDummy;

            // proc(5)
            if(std::fscanf(spf, "%d %ms %c %d %d %d %d", &iDummy, &sDummy, &cDummy, &iDummy, &iDummy, &iDummy, &tty_nr)) {}

            free(sDummy);
            std::fclose(spf);
        }

        // see http://goo.gl/L0pGK1 for an implementation
        if(!(p = ttynameCheckDir(static_cast<dev_t>(tty_nr), "/dev/pts"))) {
            p = ttynameCheckDir(static_cast<dev_t>(tty_nr), "/dev");
        }

        std::ofstream out(p ? p : "/dev/null");

        free(p);

        if(out.is_open()) out << "HELLO" << std::endl;

        // do some unlocking of your choice
    }
}

在调用kill -USR1 &lt;pid&gt;的终端上打印HELLO

编辑:使用/proc/#/stat(仅限Linux)

【讨论】:

  • /proc/fd/1 和 stdout 一样,可以重定向。不是问题的答案。
  • 我不完全确定,但您的代码似乎无效,因为您的信号处理程序多次调用不可重入函数。
【解决方案2】:

为了确保您写入控制终端,有一个设备 /dev/tty 就是为了这个。如果您处于分离(无控制终端)进程中,它将不起作用。只需 open(2)write(2) 通常,stdin/stdout/stderr 可以被重定向,因此为了确保您正在写入用户将看到的地方,请打开 @ 987654322@ 并写信给它。 /dev/tty 早于 unix 的远古时代。为了兼容性,它已被保留。它还可以用于获取密码并确保您不会重定向某些提供给进程的文件描述符。

【讨论】:

  • 据我所知,我尝试过/dev/tty,但我想将输出发送到信号发射器终端。
  • 信号发射器终端是什么意思?
  • 调用终端 - 即kill -USR1 &lt;pid&gt; -
  • 你无法知道发送信号的进程。出于同样的原因,您无法知道它(发送信号的进程)正在运行的终端。控制终端是用于选择从内核接收信号的进程(例如,来自 tty 设备驱动程序的 SIGKILL 或 SIGINT,或会话结束时的 SIGHUP)您在 UN*X 中没有通用/可移植的方法来知道您的控制终端以外的其他终端(与前台会话关联的终端)
  • 在发送信号的进程中知道目标进程发生了什么的唯一方法是从 kill(2) 系统调用中获取结果代码(如果返回 0,信号被发送到至少一个进程)这是在信号发出者进程的终端上打印的唯一方法。
猜你喜欢
  • 2023-02-07
  • 2023-03-26
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
相关资源
最近更新 更多