向我的linux守护程序发送消息的最简单方法是什么?



向我的linux守护程序发送消息的最简单方法是什么?myapp foo bar是否有可能调用回调而不是启动新进程?与守护程序通信的标准方式是什么?我最合理的选择是在/var/run中粘贴PID并创建命名管道或套接字吗?

在命令行上运行的应用程序与守护进程通信的标准方式是什么?我假设当我输入myapp foo bar时,不可能要求linux调用回调?

在命令行上运行的应用程序与其守护进程通信的标准方式是什么?

有很多方法可以做到这一点:

Dropboxes and Signals

不同的位置被用来存储"pid文件"。包含一个守护进程的进程ID号:/var/run/<app>/<app>.pid,/var/run/<app>.pid(感谢@Adam Katz的编辑),/run/<app>/<app>.pid,/run/<app>.pid,(参见Askubuntu:为什么/var/run迁移到/run?)

当守护进程的pid已知时,命令行程序(作为单独的进程运行)可以通过以下方式与守护进程通信:

  1. 将内容写入预先安排的位置。这可以是一个普通的文件,一个数据库表,或者任何方便服务器可读的位置。
  2. 向守护进程发送信号。在本地执行此操作的常见方法是使用kill系统调用int kill(pid_t pid, int sig);

老派示例:服务器复用守护进程xinetd在收到SIGHUP后会重新读取其配置文件。

发送信号的方法已经被inotifyAPI冗余,其中一个进程可以订阅文件系统事件。当您不希望守护进程对每次文件更改都采取行动时,使用信号是有用的,因为不是每次更改都可能使文件处于有效状态,就像修改系统配置文件一样。

FIFO或Pipe

fifo或管道只是一个特殊的文件,它阻止进程读取它,直到其他进程写入它。您可以使用mkfifo在文件系统中创建一个命名管道/fifo。唯一棘手的事情是管道通常应该在没有缓冲的情况下打开,例如使用open()而不是fopen()。脚本语言有时会为管道友好的读/写提供便利:Perl有一个line-buffered模式,$|=1对管道很有用。

更常见的是,您可以在命令行中看到匿名管道,使用|符号将命令作为单独的进程执行。

<标题>

套接字像mySQL这样的新东西怎么样?mysql数据库系统由命令行客户端mysql和服务器mysqld组成,还可以为本地机器或internet上的其他客户端提供服务。

mySQL使用socket通信。服务器监听套接字以获取连接,并分叉新进程,将套接字描述符提供给子进程进行处理。当子进程完成处理后,它可以退出。

有UNIX套接字和Internet套接字,它们具有不同的命名空间。在Linux上用C语言编程套接字的一个指南是GNU C库手册中的套接字章节。

无等待I/O是分岔进程的另一种选择。这是在C中使用select()系统调用完成的,它允许进程等待一个或多个文件(包括套接字)上的事件或超时。GNU C库文档包括一个无等待I/O套接字服务器示例

NodeJS是Javascript语言的服务器,作为使用无等待I/O的单线程服务器编写,并表明这些技术在现代系统中仍然相关。

<标题>

"Callbacks"h1> p>我假设它不可能要求linux调用回调当我在myapp foo酒吧?. 但是可能工作量太大,不值得这么麻烦。

当你在"Linux"中输入myapp foo bar时,这不是Linux,你是在命令shell中输入它,它是一个独立于其他程序运行的程序。

所以,除非你想要的功能内置在命令shell中,否则命令shell通常无法在不启动新进程的情况下向其他程序发送消息。

许多(但不是全部)Linux系统的默认命令shell是/bin/bash。为了与侦听bash的套接字的守护进程通信,我们需要bash中的套接字打开过程。而且,它确实存在!

可以监听bash中的套接字。这是守护进程的基础:

From: Simple Socket Server in Bash?dtmilano的回答:

Q:我有一个简单的调试解决方案,它将东西写入127.0.0.1:4444,我希望能够简单地从bash绑定一个端口并打印遇到的所有内容。有简单的方法吗?

:

$ exec 3<>/dev/tcp/127.0.0.1/4444

$ cat <&3

还可以从bash打开一个套接字到远程进程,即与守护进程通信:

From: TCP connection, bash only

我们知道exec 5<>"/dev/tcp/${SERVER}/${PORT}"将TCP链接重定向到文件描述符5作为输入和输出。

并不是所有的bash程序都是用TCP支持编译的。它显然依赖于linux发行版。至少根据William Pursell对这个答案的评论

除了bash,还有其他的shell。许多贝壳是在nix时代开发出来的。kshKorn shell。cshC-shell。Bourne shellsh。灰壳。维基百科有一个壳的列表。而且这些shell各有各的优点和缺点,彼此的格式并不完全兼容!

快进大约30年,现在没有那么多常用的了。

但是这里有一个重要的特性:每个用户可以选择自己的登录shell. 参见chsh命令

所以我在这里的意思是,如果bash不支持你需要做的通信,你可以设置一个命令shell,在那里可以发送特殊的消息,而不需要打开一个新的进程。这可能会为您节省几毫秒的时间,但通常不值得。但没有什么能阻止你。您甚至可以像https://stackoverflow.com/a/209670/103081中建议的那样,设置一个ipython命令shell, python可以导入与专用守护进程进行套接字通信所需的大部分内容。

你的帖子里有太多低级问题,所以它们不可能都在一个简短的回复中得到回答。另外,有些问题是口味比较请求,我的意思是"什么是最好的方法?"——这类问题通常是不受欢迎的。尽管如此,我还是会尽量提供你可以继续使用的基本参考。

发送消息到我的linux守护程序最简单的方法是什么?

没有这样的方法,除非你已经在使用提供这种方法的框架。守护进程太不一样了。有些只需要一组简单的固定消息,有些则需要对内部数据进行复杂的重新配置和动态修改。主要的方法是:

  1. Unix信号确实是提供受保护(稍微简化,只有同一用户或超级用户可以发送它们),幂等(重复不得改变信号含义),非参数化消息的最简单方式;这样的消息集是非常有限的(在Linux中大约50个自由使用的消息集)。它们以异步方式传递,但可以在目标应用程序中转换为内部消息队列成员。它们的主要用途是简单的消息,如"优雅地停止","重新读取配置"或"打开调试消息"。
  2. Unix域套接字是任何交互的基本IPC传输(除了共享内存更好的最快速的交互)。它们允许数据报(如UDP)、字节流(如TCP)和消息流(如SCTP或SPX)。监听套接字应在文件系统中以客户端已知的路径表示;Unix文件访问权限将控制对它的访问,或者您可以显式地检查凭据。实际上,任何协议都可以建立在这样的套接字上,但只有来自相同运行操作系统的客户端才能连接它,这样的套接字在虚拟化情况下即使从主机操作系统也不会自动可见。
  3. 非管道式IPC:共享内存和信号量可以用于高负载交互,但它们需要严格的使用规范。这种接口有两个版本(SysV和Posix)。
  4. Internet域套接字提供与Unix域套接字相同的传输,允许来自任何远程客户端(不一定在同一操作系统上)的访问,但不自动提供访问检查,因此需要客户端身份验证。通常也需要传输保护(SSL/TLS等)。
  5. 通过套接字接口提供了各种框架,这些框架实现了所需功能的某些部分,如注册、端点发布、服务器搜索等。对于本地交互,现在从Dbus开始,它是面向消息的,允许在公共操作系统空间或用户本地空间中使用命名服务器和类型消息。
  6. 不同的全网消息传输是在过去几年开发的(AMQP, ZeroMQ, Apache Kafka等),它们是为在分布式网络中使用而设计的,但通常不需要任何认证。

自制守护进程的主要问题是,您必须显式地附加这些接口中的任何一个,并提供一个框架来侦听、解码和处理传入的消息。如果您的应用程序已经是消息驱动的,那么您可以将其放入设计为消息驱动的环境中(Erlang、J2EE…),除非您害怕重写为另一种语言:)

是否有可能myapp foo bar可以调用回调而不是开始一个新的进程?

这是一个与风格相关的问题。您可以以与长期运行的控制工具相同的方式命名控制工具。在实践中有这样的例子:SysV init (telinit只是方便的名称),firefox(没有-no-remote,它试图连接到已经运行的实例),但通常,单独的名称是首选:

  • apachectl启动/停止/控制守护进程,但守护进程名称为httpd;
  • rndc用于named,gdc用于gated,等等

如果一个守护进程二进制文件非常大,那么每次启动一个小控制消息的成本太高,应该避免。但是如果你真的想这样做,确定两件事:

  • 您是否希望它自动启动,除非找到正在运行的实例?
  • 如何区分守护进程启动请求和控制请求?

如果你对这两个问题都有强有力的答案,你就不必担心。

与守护进程通信的标准方式是什么?

不,没有单一的标准方式。有一些标准的方法,见上文。一个人应该在确定了利弊之后选择一条路。

是我最合理的选择坚持PID在/var/run和创建一个命名管道或套接字?

同样,参见上面,但是您知道,除非守护进程具有根权限,否则/run (/var/run)是不可写的。非根守护进程应该完全使用另一个目录(例如,~/run/作为其专用用户的主目录),或者提供一个可写的子目录。

我假设它不可能要求linux调用回调当我在myapp foo酒吧?

你又问"callback",我不太明白它到底是什么意思。如果您的守护进程是在事件驱动的环境之外用命令式语言编写的,则应该显式地实现从其他进程接收的任何消息。对于Unix信号,您编写信号接收函数并配置进程以在传入信号时启动它们。对于套接字,您需要创建套接字,给它一个已知的地址,使它进入侦听模式,并提供代码来接受传入的连接,收集和解码消息等。只有在已经是事件驱动的环境中,您才能使用标准方法。

对于Erlang,这种远程控制通常是通过使用gen_server:call()或类似方法连接到守护节点和RPC请求来实现的。所谓的Erlang进程在通用代码中处理此过程,而不需要实现请求者是同一节点上的另一个进程或来自单独节点的情况。

有一些框架已经在过程环境中实现了一些这种需求;例如,Dbus客户端库可以用以下方式编写:

  • 为Dbus套接字监听创建一个单独的线程;
  • 接收传入消息并调用指定的回调,

但这也有自己的缺点:

  • 回调在自己的线程中运行;你们应提供适当的同步,以避免数据损坏;
  • 消息速率大,流量控制至少太粗糙,甚至不可能,在守护进程意识到总线连接应该停止之前,它可能会提前溢出。

总之,你最初的问题就像"我怎样才能以一种高效的方式到达我朋友家?"如果你的朋友住在隔壁,你可以简单地走20米,或者你可以骑自行车,或者你需要叫出租车,或者你需要租一艘宇宙飞船到达月球背面:)你应该反复缩小你的要求,直到一个单一的变体。

最新更新