将消息发送到我的linux守护程序应用程序的最简单方法是什么? myapp foo bar
是否可以调用回调而不是启动新进程?什么是与守护进程通信的标准方法?我最合理的选择是将PID粘贴在/var/run
中并创建命名管道或套接字?
什么是在命令行上运行的应用程序与其守护程序进程通信的标准方式?当我输入myapp foo bar
时,我假设无法让linux调用回调?
答案 0 :(得分:11)
什么是在命令行上运行的应用程序与其守护程序进程通信的标准方式?
有很多方法可以做到这一点:
正在使用各种位置存储&#34; pid文件&#34;包含守护程序的进程ID号:/var/run/<app>/<app>.pid
,/var/run/<app>.pid
(感谢@Adam Katz进行编辑),/run/<app>/<app>.pid
,/run/<app>.pid
,(请参阅Askubuntu: Why has /var/run been migrated to /run? )。
当守护进程的pid
已知时,命令行程序(作为单独进程运行)可以通过以下方式与守护进程通信:
int kill(pid_t pid, int sig);
。 Old School示例:服务器多路复用守护程序xinetd将在收到SIGHUP后重新读取其配置文件。
发送信号方法已被inotify
API冗余,因此进程可以订阅文件系统事件。当您不希望守护程序对每个文件更改进行操作时,使用信号非常有用,因为并非每次更改都可能使文件处于有效状态,如修改系统配置文件时。
fifo或pipe只是一个特殊文件,它阻止进程读取它,直到其他进程写入它为止。您可以使用mkfifo
在文件系统中创建命名管道/ fifo。关于这一点唯一棘手的问题是管道通常应该是无缓冲的,例如,使用open()
而不是fopen()
。脚本语言有时会为管道友好的读/写提供便利:Perl
设置了line-buffered
模式,其中$|=1
对管道非常有用。
更常见的是,您会在命令行上看到匿名管道,并使用|
符号分隔命令,这些命令作为单独的进程执行。
像mySQL这样的新东西怎么样? mysql
数据库系统由命令行客户端mysql
和服务器mysqld
组成,也可以在本地计算机或Internet上为其他客户端提供服务。
mySQL使用socket
进行通信。服务器侦听套接字以进行连接,并分叉新进程,为子进程提供套接字描述符以进行处理。当孩子完成处理时,它可以退出。
有UNIX套接字和Internet套接字,具有不同的命名空间。在Linux上用C编程套接字的一个指南是sockets chapter of the The GNU C Library manual。
不等待I / O是分离进程的替代方法。这是在C中使用select()
系统调用完成的,该调用允许进程等待一个或多个文件(包括套接字)上的事件或超时。 GNU C Library文档包括a no-wait I/O socket server example
NodeJS是Javascript语言的服务器,使用无等待I / O编写为单线程服务器,并表明这些技术在现代系统中仍然相关。
我假设当我输入myapp foo bar时无法让linux调用回调?
<强>也许即可。但是值得努力可能是太多的工作。
当您在&#34; Linux&#34;中键入myapp foo bar
,而不是Linux时,您正在键入命令shell,这是一个在自己的进程中运行的程序,与所有内容分开其他
因此,除非您想要的功能内置于命令shell中,否则通常无法在不启动新进程的情况下将该命令shell发送到其他程序。
许多(但不是全部)Linux系统的默认命令shell是/bin/bash
。要与监听来自bash
的套接字的守护进程通信,我们需要bash
中的套接字打开过程。而且,果然,它存在!
可以在bash
中收听套接字。这是守护进程的基础:
来自:Simple Socket Server in Bash? answer by dtmilano:
问:我有一个简单的调试解决方案,可以将内容写入127.0.0.1:4444,我希望能够简单地从bash绑定一个端口并打印出来的所有内容。有一个简单的方法吗?答:
$ exec 3&lt;&gt; /dev/tcp/127.0.0.1/4444
$ cat&lt;&amp; 3
还可以打开从bash到远程进程的套接字,即与守护进程通信:
我们学习exec 5<>"/dev/tcp/${SERVER}/${PORT}"
将TCP链接重定向到文件描述符5,用于输入和输出。
并非所有bash
程序都是使用TCP支持编译的。它显然依赖于Linux发行版。至少根据on this answer
除bash
之外还有其他贝壳。许多炮弹都是在* nix时代发展起来的。 ksh
Korn shell。 csh
C-shell。 Bourne shell sh
。灰壳。维基百科保持list of shells。而这些炮弹各有各的优缺点,并不完全兼容彼此的格式!
快进约30年,现在还没有这么多共同使用。
但这里存在一个重要特征:每个用户都可以选择自己的登录shell 。请参阅chsh
命令。
所以我要去的地方是,如果bash
不支持你需要做的通信,你可以设置一个命令shell,可以在不打开新进程的情况下发送特殊消息。这可能会为您节省几毫秒的时间,而且通常不值得。但没有什么能阻止你。您甚至可以按https://stackoverflow.com/a/209670/103081中的建议设置ipython命令shell,python可以导入与您的专用守护进程进行套接字通信所需的大部分内容。
答案 1 :(得分:3)
您的帖子中存在太多劣质问题,因此无法在一个紧凑的回复中回答这些问题。此外,一些问题就像品味比较请求 - 我的意思是&#34;什么是最好的方式?&#34; - 这种问题通常不喜欢SO。尽管如此,我还是尝试提供至少基本的参考资料,你可以继续。
将消息发送到我的linux守护程序应用程序的最简单方法是什么?
除非你已经使用了一些提供这种方式的框架,否则就没有这种方法。守护进程太不同了。有些只需要一组简单的固定消息,有些需要复杂的重新配置和内部数据的即时修改。主要方法是:
自制守护进程的主要问题是您应明确附加任何这些接口,并提供监听,解码和处理传入消息的框架。如果你的应用程序已经是消息驱动的,你可以把它放到一个由设计消息驱动的环境中(Erlang,J2EE ......),除非你害怕重写另一种语言:)
myapp foo bar是否可以调用回调而不是启动新进程?
它与风格相关的问题比主要问题更多。您可以使用与长时间运行控制工具相同的方式命名控制工具。在实践中有这样的例子:SysV init(telinit
只是便利名称),firefox(没有-no-remote它试图连接到已经运行的实例),但通常,首选单独的名称:
apachectl
启动/停止/控制守护程序但守护程序名称为httpd
; rndc
代表named
,gdc
代表gated
等。如果一个守护进程二进制文件是一个非常胖的人,每次为一个小的控制消息启动它的成本太高,应该避免。但如果你真的想这样做,请确定两件事:
如果您对这两个问题都有很好的答案,那么您无需担心。
与守护进程通信的标准方法是什么?
不,没有单标准方式。有几种标准方法,见上文。人们应该根据确定的利弊选择一种方式。
在/ var / run中粘贴PID并创建命名管道或套接字是我最合理的选择吗?
再次,请参阅上文,但您知道,除非守护程序具有root权限,否则/ run(/ var / run)是不可写的。非root守护进程应使用完全另一个目录(例如〜/ run /用于其专用用户主目录)或提供可写子目录。
我假设当我输入myapp foo bar时无法让linux调用回调?
你再次要求&#34;回调&#34;我不明白它究竟代表什么。如果您的守护程序是在事件驱动的环境中使用命令式语言编写的,则应明确实现从其他进程接收的任何消息。对于Unix信号,您可以编写信号接收功能并配置进程以在输入信号上启动它们。对于套接字,您应创建套接字,为其提供已知地址,将其置于侦听模式并提供接受传入连接的代码,收集和解码消息等。仅对于已经事件驱动的环境,您可以使用标准方法。
对于Erlang,这种远程控制通常使用gen_server:call()或analog实现为连接到守护程序节点和RPC请求。被调用的Erlang进程在通用代码中处理它,而不需要实现请求者是同一节点或另一个节点上的另一个进程的情况。
有些框架已经在程序环境中实现了一些这样的需求;例如Dbus客户端库可以用它们
的方式编写但这有其自身的缺点:
总结一下,您最初的问题就像是&#34;我如何以有效的方式到达我朋友的家?&#34;最少的细节。如果你的朋友住在隔壁,你可以步行20米,或者你可以骑自行车,或者你需要打电话给出租车,或者你需要租一艘太空船到达月球的背面:)你应该反复缩小你的要求直到一个变体仍然存在。