在命令行上运行的应用程序与其守护进程进行通信的标准方式是什么?
有多种方法可以做到这一点:
Dropbox 和信号
各种位置被用来存储包含守护进程进程 ID 号的“pid 文件”:/var/run/<app>/<app>.pid
, /var/run/<app>.pid
(感谢@Adam Katz 的编辑),/run/<app>/<app>.pid
, /run/<app>.pid
, (see Askubuntu:为什么 /var/run 被迁移到 /run? https://askubuntu.com/questions/57297/why-has-var-run-been-migrated-to-run).
当。。。的时候pid
守护进程的已知信息是,命令行程序(作为单独的进程运行)可以通过以下方式与守护进程进行通信:
- 将一些东西写到预先安排的地方。这可以是普通文件、数据库表或服务器可读的任何方便的位置。
- 向守护进程发送信号。在本地执行此操作的常见方法是使用 Kill 系统调用,int kill(pid_t pid, int sig); http://linux.die.net/man/2/kill.
老派示例:服务器多路复用守护进程xinetd http://www.ibm.com/developerworks/aix/library/au-spunix-inetd/收到 SIGHUP 后会重新加载其配置文件。
发送信号方法已被冗余inotify API http://linux.die.net/man/7/inotify进程可以借此订阅文件系统事件。当您不希望守护进程执行操作时,使用信号非常有用every文件更改,因为并非每次更改都可以使文件保持有效状态,就像修改系统配置文件时一样。
先进先出或管道
fifo 或管道只是一个特殊文件,它会阻止进程读取它,直到其他进程写入它为止。您可以在文件系统中创建命名管道/fifomkfifo http://linux.die.net/man/1/mkfifo。唯一棘手的事情是管道通常应该在无缓冲的情况下打开,例如和open()
相对于fopen()
。脚本语言有时会为管道友好的读/写提供便利:Perl
had a line-buffered
模式设置为$|=1
这对管道很有用。
更常见的是,您总是在命令行上看到匿名管道|
符号分隔作为单独进程执行的命令。
Sockets
更新的东西怎么样,比如 mySQL?这mysql
数据库系统由命令行客户端组成mysql
和服务器mysqld
并且还可以在本地计算机上或通过互联网为其他客户端提供服务。
mySQL 使用以下方式进行通信socket
。服务器监听套接字的连接,并分叉新进程,将套接字描述符提供给子进程进行处理。当子进程完成处理后,它可以退出。
有 UNIX 套接字和 Internet 套接字,它们具有不同的命名空间。在 Linux 上用 C 语言编程套接字的指南之一是GNU C 库手册中的套接字章节 http://www.gnu.org/software/libc/manual/html_node/Sockets.html#Sockets.
无等待 I/O 是分叉进程的替代方案。这是用 C 语言完成的select()
系统调用,它允许进程等待一个或多个文件上的事件,包括套接字或超时。 GNU C 库文档包括无等待 I/O 套接字服务器示例 http://www.gnu.org/software/libc/manual/html_node/Server-Example.html#Server-Example
NodeJS http://nodejs.org/是 Javascript 语言的服务器,使用无等待 I/O 编写为单线程服务器,并表明这些技术在现代系统中仍然相关。
“回调”
我假设当我输入 myapp foo bar 时不可能要求 linux 调用回调?
Maybe。但可能工作量太大,不值得这么麻烦。
当您输入时myapp foo bar
输入“Linux”,那不是 Linux,您将其输入到命令 shell 中,这是一个在其自己的进程中运行的程序,与其他所有程序分开。
因此,除非您想要的功能内置在命令 shell 中,否则该命令 shell 通常无法在不启动新进程的情况下向其他程序发送消息。
许多(但不是全部)Linux 系统的默认命令 shell 是/bin/bash
。与监听套接字的守护进程进行通信bash
我们需要一个套接字打开过程bash
。而且,果然,它存在!
一个人可以监听一个套接字bash
。这是守护进程的基础:
From: Bash 中的简单套接字服务器? https://stackoverflow.com/questions/4739196/simple-socket-server-in-bash dtmilano 的回答 https://stackoverflow.com/a/4743398/103081:
问:我有一个简单的调试解决方案,它将内容写入 127.0.0.1:4444,我希望能够简单地从 bash 绑定端口并打印遇到的所有内容。是否有捷径可寻?
A:
$ 执行3/dev/tcp/127.0.0.1/4444
$ 猫
还可以从 bash 打开一个远程进程的套接字,即与守护进程通信:
From: TCP 连接,仅限 bash https://stackoverflow.com/questions/7765004/tcp-connection-bash-only
我们学习exec 5<>"/dev/tcp/${SERVER}/${PORT}"
将 TCP 链接重定向到文件描述符 5 以进行输入和输出。
Not all bash
程序是在 TCP 支持下编译的。它显然依赖于 Linux 发行版。至少根据评论关于这个答案 https://stackoverflow.com/a/7765082/103081 by 威廉·珀塞尔 https://stackoverflow.com/users/140750/william-pursell
除此之外还有其他的贝壳bash
。许多 shell 是在 *nix 时代开发的。ksh
科恩壳。csh
C壳。伯恩外壳sh
。灰壳。维基百科保留了一个贝壳列表 http://en.wikipedia.org/wiki/Comparison_of_command_shells。而且这些 shell 各有各的优缺点,并且彼此的格式并不完全兼容!
快进大约 30 年,现在常用的已经不多了。
但这里有一个重要的特征:每个用户可以选择自己的登录 shell。请参阅chsh http://linux.die.net/man/1/chsh命令。
所以我要去的地方是如果bash
不支持您需要执行的通信,您可以设置一个命令外壳,可以在其中发送特殊消息而无需打开新进程。这可能会节省您几毫秒的时间,但通常不值得。但没有什么可以阻止你。您甚至可以设置一个 ipython 命令 shell,如中所建议的https://stackoverflow.com/a/209670/103081 https://stackoverflow.com/a/209670/103081,并且 python 可以导入与专用守护进程进行套接字通信所需的大部分内容。