16

这个问题与编程无关,但对程序员来说肯定很重要。

我写了一个简单的 smtp 服务器,当我从控制台运行它时一切都很好,除了它阻塞了命令行。

我知道我可以通过

nohup ... &

或通过 screen / tmux 等

但问题是,我应该如何实现它在后台运行的程序,并且系统管理员会很高兴设置它并管理该过程?

一些比我更有经验的人在golang-nuts写道,他们不使用 fork 等,而是使用来自 monit 等形式的一些“包装器”。

目标平台是基于 Debian 的,盒子上的所有其他东西都是基于 init.d 的。

该主题的任何好的资源或编写良好的示例项目的来源?

4

5 回答 5

24

正如尼克提到的, Supervisord是一个很好的选择,在我的经验中也很有效。

Nick 提到了分叉本身的问题,AFAICT 工作得很好。问题不是分叉,而是放弃特权。由于 Go 运行时启动多路复用 goroutine 的线程池的方式(当 GOMAXPROX > 1 时),setuid 系统调用不是删除权限的可靠方法

相反,您应该以非特权用户身份运行程序并使用setcap实用程序授予它所需的权限。

例如,要允许绑定到低端口号(如 80)运行,需要在可执行文件上运行一次 setcap:sudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary

您可能需要安装 setcap:sudo aptitude install libcap2-bin

于 2013-01-29T00:13:07.810 回答
16

已经有很好的答案,但我会添加一些额外的信息。

您无需安装其他软件(例如supervisord在 Debian 上)来处理后台进程。

Debian 带有一个名为的工具,它是在脚本start-stop-daemon中启动守护进程的标准方法。init.d如果程序不自己执行此操作,它还可以为您将进程置于后台。看看--background选项。

用作/etc/init.d/skeleton您的 init 脚本的基础,但更改do_start()函数如下:

start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \
    --background --exec $DAEMON --test > /dev/null \
            || return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \
    --background --exec $DAEMON -- $DAEMON_ARGS \
            || return 2

我还添加了--make-pidfile为您创建 PID 文件的选项。

如果您需要以安全的方式切换到不同的用户,还有一个--chuid选项。

在 Ubuntu 和 RHEL/CentOS/SL 6.X 上,最简单的方法是编写upstart作业配置文件。只需放入exec /usr/sbin/yourprogram配置/etc/init/yourprogram.conf文件即可。对于暴发户,无需强制程序在后台运行。不要使用传统守护程序添加expect fork或您需要的。expect daemon对于暴发户,如果进程不分叉会更好。

于 2013-02-02T03:39:34.190 回答
10

不久前我写了一篇关于这个的博客文章。守护进程的想法对我来说似乎是错误的,因为它让您有很多其他事情要担心(例如,当它失败时会发生什么?您如何管理进程重启?您如何处理日志记录、工作目录、内核、系统重启, ETC...)

事实证明,如果你尝试做所有这些,事情会变得容易得多。

于 2013-01-27T05:45:44.427 回答
5

根据我的经验, Supervisord对此非常有效。

您编写应用程序以在命令行上运行,打印内容等,supervisord 负责所有守护进程,如果出错则重新启动,速率限制等

我相信以传统的 unix 方式将 go 程序分叉到后台是很困难的,因为运行时在运行您的main()例程之前会启动一些线程

于 2013-01-26T13:17:53.840 回答
3

但问题是,我应该如何实现它在后台运行的程序,并且系统管理员会很高兴设置它并管理该过程?

这里有一些想法。

提供包和存储库

安装软件是一回事,维护和运行它是完全不同的故事。当然,我可以下载一个 zip,解压缩,将文件放入适当的目录(请记住,包通常分散在整个文件系统中),创建一个系统用户来运行守护程序,设置相应的权限。但这很乏味,容易出错(这将导致大量的票如“呸!不运行!修复它!”)并且如果要在许多系统上安装该软件几乎不实用。

所以我们需要一个包来降低采用率。为这些软件包提供存储库通常不是火箭科学,并且使安装和/或更新更加容易。“下载->分发->安装/更新”和单个命令/服务器之间存在差异

$ awesomePm update coolApplication

至少为基于 RedHat 和 Debian 的系统提供软件包。就个人而言,我会选择 CentOS(这将使您的软件包与几乎任何 RHEL 衍生产品兼容)和基本的 Debian。后者也应该使为 Ubuntu 提供一个包变得微不足道。由于我不再使用 Debian 或衍生产品,我不太确定它们是否真的兼容,我上次构建.deb.

提供适当的文件。记录安装的内容、位置和原因。提供指向相应文档的链接。对依赖项的手册页引用就足够了。这样,即使是最没有经验的管理员也可以配置您的包。

使用最具防御性、理智的默认设置

关于 golang 的特别说明:默认情况下,大多数包构建工具会剥离包中包含的二进制文件。Go 不支持这一点,所以请注意这里。

完整

没有什么比不完整的包裹更烦人的了。

尽可能使用 syslog并遵守其约定。这样,您的日志将被放置到系统管理员期望它们的位置,并且如果它们自动过期,它们会得到处理,防止您的应用程序导致磁盘满载。如果系统管理员想要对您的应用程序的日志进行特殊处理,他会以这种方式进行配置。

不要通过您的应用程序轮换日志。用户可以选择如何处理它们(这可能与他们的 SLA 相关)。即使您使日志轮换的方式可配置,管理员也必须学习如何配置它——这会引入不必要的冗余。

如果您必须写入日志文件,请遵守目标系统的日志记录策略并提供日志轮换配置文件。您不希望您的应用程序因为机器磁盘空间不足而导致停机,对吗?

使用系统工具而不是重新发明轮子。如果您的应用程序需要进行一些维护,请不要费心在应用程序中使用调度程序。为维护编写一个专门的工具(单体应用程序是如此的 00 年代)并利用cron. 专门将相应的文件添加到/etc/cron*目录之一。

提供适当的初始化脚本!这样,管理员可以使用众所周知的工具systemctl来管理应用程序的启动和关闭。su当您必须对用户或使用sudo -u启动时调用 shell 脚本时,这非常烦人。即使调用此脚本@onboot,与标准的偏差也很烦人。仅仅因为启动方法有效,并不意味着应该使用它。

添加 SE-Linux 配置文件的奖励积分!

不言而喻,但我经常看到配置错误的包,所以:测试你的包!从目标操作系统的最小安装开始,安装你的包并确保它按预期运行。检查您提供的每个配置。

如果您打算将一个软件包放入 Debian 官方存储库,您应该计划一些时间:Debian 之所以如此稳定,是因为对软件包的要求非常严格,即使您满足所有要求,您也必须全力以赴从不稳定到稳定的测试方式。

精确

不要仅仅因为方便就使用现有用户。如果您创建 Web 应用程序,请不要重用“apache”或“www”用户。创建一个专用于您的包的用户并将此用户添加到相应的组中。

坚持最少必要权限的原则。几乎没有理由拥有二进制世界可执行文件,更不用说世界可写(这将是一个极端的安全漏洞)。如果应用程序未运行,您在 SO 上经常看到的建议是将权限设置为 [0]777,这允许每个用户对文件进行任何修改。实际上,几乎没有理由让任何用户都可以写入二进制文件:root,无论如何都会进行更新,总是可以写任何东西。所以权限应该是0550对于二进制文件。该原则也适用于数据目录等。在这里投入一些时间和精力。您不希望您的应用程序成为成功攻击的载体,对吗?即使是潜在的安全风险也会对您和您的声誉造成反击。我倾向于将所有数据文件设置0600为需要由应用程序的系统用户写入的文件、0400只读文件和0500二进制文件。然后,我做了一个细粒度的分析组权限应该是什么。例如:一个组可能会更改 Web 应用程序的各个模板——但很可能不会更改资源目录子树的目录结构。

如果你把精力放在安全上,你就会增加信任。请注意,在决定是否采用包之前,通常会检查包的安全影响。

遵守FHS(!!)!即便如此:仅仅因为你可以在 下做任何事情/opt/yourapplication,这样做并不总是一个好主意。而是分别安装到/usr/var(假设您的应用程序在启动时不是必需的)。

如果您有依赖项,请定义它们。不要仅仅假设存在一个包。

如果您对本地 SMTP 服务器有依赖关系,请不要声明对postfix. 也许管理员更喜欢 sendmail(无论出于何种原因)。因此,请改为定义对mail-transport-agent(Debian) 或mta(RH, iirc) 的依赖项。

结论

这就是我对优秀软件的期望——与现有软件很好地集成,并使其易于安装、维护、配置和运行,而无需学习冗余配置。如果我看到一个包的 SELinux 配置文件,这确实给了供应商一个好处——除非配置文件非常草率,否则这表明供应商非常重视安全性。

于 2016-01-05T15:55:11.443 回答