我当前正在屏幕中运行服务器控制台程序,因为我需要读取它并偶尔发送命令。
我想在后台将应用程序作为守护进程运行(使用 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 程序。据我所知,tail
GNU 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
。