这个问题与编程没有严格的关系,但对程序员来说肯定很重要。
我写了一个简单的smtp服务器,当我从控制台运行它时一切都很好,除非它阻止了命令行。
我知道我可以通过
运行它nohup ... &
或通过screen / tmux等
但问题是,如何实施我在后台运行的程序,系统管理员很乐意设置它并管理流程?
有些人比我更有经验,在golang-nuts写道,他们不使用fork等,并使用monit等形式的“包装”。
目标平台基于Debian,盒子上的所有其他内容都是基于init.d。
该主题的任何好资源或编写良好的示例项目的来源?
答案 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 fork
或expect 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配置文件,这确实给了供应商一个奖励 - 除非配置文件非常草率,它表明供应商的安全性非常严重。