如何制作将输出发送到进程的 shell 脚本

如何制作将输出发送到进程的 shell 脚本

我当前正在屏幕中运行服务器控制台程序,因为我需要读取它并偶尔发送命令。

我想在后台将应用程序作为守护进程运行(使用 init 启动/停止它)。

我可以tail -f记录日志,但这不会让我向进程发送输入。

有什么方法可以设置它,以便我可以读取和发送输入,但仍然让它在后台运行?

我还希望能够从不同的进程向守护进程发送输入(例如,可以发送“Stop\n”命令的 shell 脚本)。

答案1

从管道读取,写入文件

如果您希望守护进程读取某个任意进程生成的输入,则需要将该进程连接到管道。这里的任意进程是您回显命令,它将在不同的上下文中运行。所以创建一个命名管道(在 UNIX 环境中通常称为 fifo)。

mkfifo /var/run/daemon.fifo
</var/run/daemon.fifo /path/to/daemond --option >daemon.log

只需将命令写入管道即可:

echo 'FORWARD 10' >/var/run/daemon.fifo
echo 'LEFT 72' >/var/run/daemon.fifo

然而,这不太可能按原样工作:当守护进程在其标准输入上看到文件结尾时,守护进程很可能会退出,这在第一个写入管道的进程终止时就会发生。您可以使用它tail -f来避免该问题。

</var/run/daemon.fifo tail -c +1 -f | {
  echo $$ >/var/run/daemon.pid
  exec /path/to/daemond --option >daemon.log
}

对于某些tail实现,您可能会被缓冲所困扰:tail进程将等待,直到积累了足够的字节来发出一些输出。我不认为这在 POSIX 工具箱中是可以解决的;如果这是一个问题,请使用简单的 C 或 Perl 或 Python 程序。据我所知,tailGNU coreutils(在 Linux 和其他地方找到)在这方面是安全的。

当您停止守护进程时,echo >/var/run/daemon.fifo将杀死该tail进程。


启动屏幕内的程序

不要直接从服务管理器调用守护进程(您真的只使用 SysV init,还是像包装脚本或 Upstart 之类的其他东西?),而是调用

screen -c daemon.screenrc -L -d -m -S daemon_name /path/to/daemond --option

由于守护进程不会是服务管理器的子进程,因此您需要确保向正确的进程发送信号。如何做到这一点取决于守护进程的启动方式和启动方式。

它是技术上可行将正在运行的进程附加到终端,但存在使程序崩溃的风险,因此这绝对不适合生产系统。

-L选项使屏幕将窗口中出现的所有内容写入文件。文件名daemon.screenrc在指令中给出logfile

相关内容