我正在 /etc/init.d 中设置服务。我正在查看其中的各种脚本,有些是用 实现的start-stop-daemon ...
,有些是用/path/to/script &
.
它们都将 pid 保存在文件中并进行一些检查。
最佳实践是什么,有什么区别,这里需要了解什么......? (一般来说)
在我的特定情况下,我在java中有一个简单的轻量级本地主机http服务器,应用程序大约每小时调用一次,它只是给出一个愚蠢的随机数(这里没有更多细节,我只是意味着它不使用文件系统或线程或任何复杂的事情,以防我的问题)
谢谢
答案1
后台作业(即以 & 开始)的 stdin、stdout 和 stderr 仍然连接到它启动的终端。它可能会突然向终端写入(例如错误消息)(“干扰”作业)前台)或暂停等待键盘输入(必须先将其置于前台)。当然,您可以将 stdout 和 stderr 重定向到文件或 /dev/null 以防止后台作业写入终端。
后台作业也可以放在前台 - 例如。当前前台作业已停止,并且fg
(foreground) 命令用于将后台作业置于前台。后台作业也可以通过来自终端的信号来实现 - 例如。 SIGHUP 当您关闭终端时,通常会结束(大多数)在终端中启动的程序。
另一方面,守护进程(例如由 init.d 自动启动的守护进程,但也可以从终端手动启动)在与任何终端断开连接的情况下运行。即使它是从终端手动启动的,守护进程也会与终端断开连接,因此它既不能写入(stdout,stderr)也不能读取(stdin)它。它还对终端“自动”发送的信号“免疫”。 (尽管您可以使用 向其发送信号kill -signal pid
)。
“后台”和“前台”是指某个终端的进程状态 - 无论是否是当前控制终端的进程。由于守护进程没有连接到终端(但已以各种方式自动与终端断开连接),因此不能说它在后台运行。守护进程只是运行的进程,不与终端关联——无论是在前台还是后台。
如果您使用ps
显示进程使用哪个终端的选项,您将看到前台和后台作业都与终端关联(例如 tty2)。另一方面,守护进程有一个“?”在这个领域里。
守护进程通常会这样做,即使它们是手动启动的。创建您自己的守护进程是一项相当多的工作 - 需要一些技巧才能将其与终端完全断开。您应该创建它自己的用户/组来运行。如果您希望它创建文件,通常必须使用 /tmp、/var/tmp 或 /var/run - 它通常不应该在其他任何地方拥有权限。由于它无法向终端报告错误,因此您应该将其写入日志文件(例如,它自己的日志文件位于 /var/log 中)。守护进程应该使用当前的 PID 在 /var/run 中创建一个条目,并且应该检查它的另一个实例是否已经在运行。如果适用,它应该尊重文件或设备的锁(/var/lock)。它应该通过重新加载配置文件并使用更新的配置来响应 SIGHUP。
另一点是大多数守护进程的工作方式。守护进程通常是单个可执行文件,可以以两种不同模式之一运行;取决于它是原始守护进程 - 父进程 - 在引导时启动还是手动启动......还是由该父进程生成的子进程。父进程通常只是等待某些事件 - 特定时间、经过的时间、尝试连接到特定网络端口或其他事件。当这种情况发生时,父进程创建一个与自身相同的子进程(使用 fork() 系统调用) - 并立即返回等待另一个事件(并且可能产生更多子进程)。它是实际执行工作的子进程 - 例如同步磁盘、运行命令(例如cron
)或建立网络连接(例如sshd
或ftpd
)。父进程和子进程之间的唯一区别是,它们具有不同的 PID,并且子进程的 PPID (Parent-PID) 是父进程的 PID - 这可用于确定进程是父进程还是子进程。因此,同一个进程必须能够以两种模式运行 - 作为等待(和生成)的父进程,或作为工作的子进程。
虽然编写守护进程并不困难,但它也不是微不足道的 - 正如您所看到的,您必须首先了解很多“技巧”。一般来说,我认为编写一个守护进程需要付出很大的努力,而与其他替代方案相比却收效甚微:
在后台作业中使用nohup
或通常是一个足够好的选择,因为即使终端关闭,它也可以使进程保持活动状态。disown
不过,将 stdout 和 stderr 重定向到文件或 /dev/null 通常是个好主意。对于更具交互性的程序,screen
将某些内容“放在一边”直到您需要时是一个好方法。 at
,batch
也crontab
值得考虑。