我应该如何在后台运行Golang进程?

时间:2013-01-26 12:45:39

标签: linux design-patterns process go

这个问题与编程没有严格的关系,但对程序员来说肯定很重要。

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

我知道我可以通过

运行它
nohup ... &

或通过screen / tmux等

但问题是,如何实施我在后台运行的程序,系统管理员很乐意设置它并管理流程?

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

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

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

5 个答案:

答案 0 :(得分:24)

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

尼克提到了分叉问题 - 分叉本身可以正常使用AFAICT。问题不是分叉,而是放弃特权。由于Go运行时启动了goroutines被多路复用的线程池(当GOMAXPROX> 1时),setuid systemcall is not a reliable way to drop permissions

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

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

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

答案 1 :(得分:16)

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

您无需在Debian上安装supervisord等其他软件来处理该过程的后台处理。

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 forkexpect daemon。使用upstart,如果进程不分叉则更好。

答案 2 :(得分:10)

我曾经写过a blog post一段时间。守护进程的想法对我来说似乎不对,因为它会让你担心很多其他事情(例如,当它失败时会发生什么?你如何管理进程重启?你如何处理日志,工作目录,核心,系统重启等等......)

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

答案 3 :(得分:5)

根据我的经验,

Supervisord对此非常有效。

你编写你的应用程序在命令行上运行,打印东西等,supervisord负责所有的守护,如果出错,重新启动,速率限制等等

我认为以传统的unix方式将程序转移到后台是很困难的,因为运行时在运行main()例程之前启动了一些线程

答案 4 :(得分:3)

  

但问题是,我应该如何实现我在后台运行的程序,系统管理员很乐意设置它并管理流程?

这里有一些想法。

提供包和存储库

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

所以我们需要一个包来降低采用的障碍。为这些软件包提供存储库通常不是火箭科学,使安装和/或更新更容易。 "下载 - >分发 - >安装/更新"之间存在差异和一个像

这样的命令/服务器
$ awesomePm update coolApplication

至少为RedHat和基于Debian的系统提供包。就个人而言,我选择CentOS(这将使您的软件包与几乎所有RHEL派生的软件兼容)和基本的Debian。后者应该使得为Ubuntu提供包也变得微不足道。由于我不再使用Debian或派生词,我不太确定它们是否真正兼容,当我上次构建.deb时出现启动问题。

提供适当的文档。记录安装的内容,位置和原因。提供相应文档的链接。 manpage对依赖项的引用就足够了。这样,您甚至可以启用最缺乏经验的管理员来配置您的包。

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

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

完成

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

尽可能使用syslog 并遵守其惯例。这样,您的日志将被放置到系统管理员期望的位置,并且如果自动过期则会处理它们,从而阻止您的应用程序使磁盘运行完全。如果系统管理员想要对您的应用程序的日志进行特殊处理,他将以这种方式进行配置。

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

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

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

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

添加SE-Linux个人资料的加分点!

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

如果您计划将一个软件包放入官方Debian存储库,您应该计划一些时间:Debian之所以稳定,是因为对软件包的要求非常紧张,即使您满足所有要求,也有从测试经过不稳定到稳定。

准确

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

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

如果您努力投入安全,您将增加信任。请注意,在采取措施之前,通常会检查包裹的安全影响。

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

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

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

结论

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