关于linux:强制CLI使用现有流程?

Force CLI to use existing process?

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

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


Whats is the standard way apps which run on the command line communicate to its daemon process?

Ok.

有很多方法可以做到这一点:好的。升降箱和信号

许多位置被用来存储包含守护进程进程ID号的"pid文件":/var/run//.pid/var/run/.pid(感谢@adam katz进行编辑)、/run//.pid/run/.pid(请参阅askubuntu:why has/var/run been migrated to/run?).好的。

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

  • 把一些东西写进预先安排好的地方。这可以是一个普通的文件、一个数据库表,或者服务器可以读取的任何方便的点。
  • 向守护进程发送信号。本地执行此操作的常见方法是使用kill系统调用int kill(pid_t pid, int sig);
  • 旧的例子:服务器多路复用守护进程xinetd在接收到叹息后将重新读取其配置文件。好的。

    inotifyAPI使发送A信号方法变得多余,因此进程可以订阅文件系统事件。当您不希望守护进程对每个文件更改都采取行动时,使用信号很有用,因为并非每个更改都会使文件保持有效状态,例如在修改系统配置文件时。好的。先进先出法

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

    更常见的是,您会在命令行中一直看到匿名管道,其中使用|符号分隔命令,这些命令作为单独的进程执行。好的。插座

    有什么更新的,比如mysql?mysql数据库系统由一个命令行客户机mysql和一个服务器mysqld组成,还可以在本地计算机或因特网上为其他客户机服务。好的。

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

    有Unix套接字和Internet套接字,具有不同的命名空间。在Linux上对C中的套接字进行编程的一个指南是GNUClibrary手册中的sockets一章。好的。

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

    nodejs是JavaScript语言的一个服务器,它使用无等待I/O作为单线程服务器编写,表明这些技术在现代系统中仍然是相关的。好的。"回调"

    I'm assuming its impossible to ask linux to call a callback when I type in myapp foo bar?

    Ok.

    也许吧。但这可能是太多的工作值得麻烦。好的。

    当您在"linux"中键入myapp foo bar时,这不是linux,而是在命令shell中键入该命令,该命令shell是一个在自己的进程中运行的程序,与其他程序不同。好的。

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

    许多(但不是所有)Linux系统的默认命令shell是/bin/bash。要与监听来自bash的套接字的守护进程通信,我们需要在bash中执行套接字打开过程。当然,它确实存在!好的。

    你可以听bash中的插座。这是守护进程的基础:好的。

    来自:bash中的简单套接字服务器?由DTMilano回答:好的。

    Q: I have a simple debugging solution which writes things to 127.0.0.1:4444 and I'd like to be able to simply bind up a port from bash and print everything that comes across. Is there an easy way to do this?

    Ok.

    A:

    Ok.

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

    Ok.

    $ cat <&3

    Ok.

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

    发件人:TCP连接,仅限bash好的。

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

    并非所有的bash程序都是用TCP支持编译的。它显然依赖于Linux发行版。至少根据威廉·珀塞尔对这个答案的评论好的。

    bash外,还有其他的贝壳。许多炮弹是在尼克斯时代研制出来的。江户十一〔9〕号壳。cshC壳。Bourne Shell sh。灰壳。维基百科保存着贝壳的列表。这些shell各有其优缺点,不完全兼容对方的格式!好的。

    快速前进大约30年,现在没有那么多的共同使用。好的。

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

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


    你的帖子里有太多的低级问题,所以不能用一个简单的答案来回答。另外,一些问题类似于味觉比较请求——我的意思是"最好的方法是什么?"-这种问题通常不受欢迎。尽管如此,我将尝试提供至少基本的参考资料,您可以继续。好的。

    Whats the easiest way to send messages to my linux daemon app?

    Ok.

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

  • Unix信号实际上是提供保护的最简单方法(稍微简化,只有同一个用户或超级用户可以发送它们)、等量(重复不改变信号含义)、非参数化消息;此类消息集非常有限(Linux中约50个自由使用的消息集)。它们是异步传递的,但可以在目标应用程序中转换为内部消息队列成员。它们的主要用途是用于简单消息,如"优雅地停止"、"重新读取配置"或"打开调试消息"。
  • Unix域套接字是任何交互的基本IPC传输(除了共享内存更好的最快的那些)。它们允许数据报(如UDP)、字节流(如TCP)和消息流(如SCTP或SPX)。在文件系统中,应使用客户端已知的路径表示侦听套接字;Unix文件访问权限将对其进行访问控制,或者您可以显式检查凭据。实际上,任何协议都可以在这些套接字上构建,但只有来自同一运行操作系统的客户机可以连接它,即使在虚拟化情况下,这些套接字也不会自动从主机操作系统中看到。
  • 非管道式IPC:共享内存和信号量可以用于高负载交互,但它们需要很强的使用规则。这种接口有两个版本(sysv和posix)。
  • Internet域套接字提供与Unix域套接字相同的传输,允许从任何远程客户端(不一定在同一操作系统上)访问,但不自动提供访问检查,因此需要进行客户端身份验证。此外,通常还需要传输保护(SSL/TLS等)。
  • 套接字接口上提供了各种框架,这些框架实现了所需功能的某些部分,如注册、端点发布、服务器搜索等。对于本地交互,这现在从面向消息的DBU开始,允许在公共操作系统空间或用户本地空间中使用命名服务器和键入的消息。
  • 过去几年开发了不同的网络消息传输(AMQP、ZeroMQ、ApacheKafka等),它们是为在分布式网络中使用而设计的,但通常没有任何身份验证。
  • 自制守护进程的主要问题是,您应该显式附加这些接口中的任何一个,并提供一个框架来监听、解码和处理传入消息。如果您的应用程序已经是消息驱动的,那么您可以将其放入由设计驱动的消息环境(erlang、j2ee…),除非您害怕重写到另一种语言:)好的。< Buff行情>

    myapp foo bar是否可以调用回调而不是启动新进程?好的。< /块引用>

    这是一个比主要问题更与风格相关的问题。可以用与长时间运行的控制工具相同的方式命名控制工具。实践中有这样的例子:sysv in it(telinit是唯一的方便名称)、firefox(没有远程,它试图连接到已经运行的实例),但一般来说,最好使用单独的名称:好的。

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

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

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

    如果你对这两个问题都有很强的回答,你就不用担心了。好的。

    Whats the standard way to communicate with a daemon?

    Ok.

    不,没有单一的标准方法。有几种标准方法,请参见上文。一个人应该选择一种坚定的利弊之道。好的。

    Is my most reasonable choice to stick the PID in /var/run and create a named pipe or a socket?

    Ok.

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

    I'm assuming its impossible to ask linux to call a callback when I type in myapp foo bar?

    Ok.

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

    对于Erlang,这种远程控制通常使用gen_server:call()或analyous实现为连接到守护进程节点和RPC请求。被调用的erlang进程用通用代码处理这个问题,不需要实现任何情况:请求者是同一节点上的另一个进程,或者是来自另一个节点的另一个进程。好的。

    有些框架已经在过程环境中实现了一些这种需求;例如,DBUS客户机库可以以某种方式编写好的。

    • 为DBUS套接字侦听创建单独的线程;
    • 接受传入消息并调用指定的回调,

    但这也有其自身的缺点:好的。

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

    总而言之,你最初的问题是"我怎样才能有效地到达我朋友的家?"细节最少。如果你的朋友住在隔壁,或者你可以骑自行车,或者你需要打电话叫出租车,或者你需要租一艘太空船到达月球的背面,你可以简单地走20米。你应该反复缩小你的需求范围,直到一个单一的变种仍然存在。好的。好啊。