写入后台进程的标准输入

写入后台进程的标准输入

我在一台 Ubuntu 10.04 机器上,并通过 ssh 在后台启动了一个服务器 (myserver &)。它运行良好,但我需要一种方法来获取服务器的标准输入,因为控制服务器的唯一方法是通过这种方法。

有没有办法获取已运行进程的标准输入,以便我可以向其写入数据(并希望读取其标准输出)?显然,如果我现在要执行此操作,我会使用 FIFO 重定向到标准输入来启动它,但不幸的是现在有点晚了。

有任何想法吗?

答案1

您可以尝试写入它的 /proc pid 目录。假设您的守护进程的 pid 是 2000,请尝试写入 /proc/2000/fd/0

答案2

您可以使用命名管道(fifo)作为输入来启动服务器:

mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
cat /tmp/srv-input | myserver &

避免服务器收到 EOF 非常重要cat > /tmp/srv-input &。至少一个进程必须以写入方式打开 fifo,这样服务器就不会收到 EOF。此命令的 PID 保存在文件中,/tmp/srv-input-cat-pid以便稍后终止。

如果您已经启动了服务器,则必须使用调试器(例如,gdb将其附加到您的进程)将其重定向stdin到 fifo:

gdb -p PID
call close(0)
call open(0, "/tmp/srv-input", 0600)

然后执行类似下面的操作将输入发送到您的服务器(如果需要,可以在另一个终端窗口中发送):

echo "command" > /tmp/srv-input

要向您的服务器发送 EOF,您需要终止cat > /tmp/srv-inputPID 已保存的进程/tmp/srv-input-cat-pid file

对于 GDB 来说,只要退出 GDB 就会发送 EOF。

答案3

与上面相同,但“cat”对我不起作用。文件在发送一个命令后就得到 EOF 并结束。

这对我有用:

#!/bin/bash

mkfifo /tmp/srv-input
tail -f /tmp/srv-input | myserver &

答案4

有一个更优雅的解决方案可以解决 tail -fcat

  • 创建一个命名管道来通过以下方式路由 STDIN mkfifo /data/in:。

  • 阻止它进行写入,因此当您的进程读取所有当前内容时它不会被关闭:sleep infinity > /data/in &

永远休眠比 更好,tailf -f /dev/null因为 tailf 使用 inotify 资源,并且每次某个应用程序向 /dev/null 发送数据时都会触发。您可以通过运行strace它来看到这一点。它也比 更好,cat > /dev/null &因为cat本身会与 STDIN 断开连接,而 STDIN 又会关闭/data/in

  • /data/in通过提供 STDIN:在后台启动您的进程application < /data/in &

这比使用尾部的管道效果更好,tail -f /data/in | application &因为只有尾部停止时管道才会终止,但如果应用程序崩溃,管道将继续运行。

  • 暂停等待应用程序完成wait $(pidof application)

这不会占用任何资源,如果应用程序崩溃,您的脚本wait将在执行后执行。如果您愿意,可以为其添加应用程序重启循环。

  • 要正常终止应用程序,请捕获系统信号并将其传递给它trap 'kill -SIGTERM $(pidof app)' SIGTERM

相关内容