This question is not strictly programming related, but for sure important for programmers.
这个问题并不是严格意义上的编程相关问题,但对程序员来说肯定很重要。
I wrote a simple smtp server, when I run it from console all is fine, except it is blocking the command line.
我编写了一个简单的smtp服务器,当我从控制台运行它时一切正常,除了它阻塞命令行。
I know I can run it via
我知道我能通过
nohup ... &
or via screen / tmux etc
或通过屏幕/ tmux等
But the question is, how should I implement my program it runs in the background and it will be a pleasure for a system administrator to set it up and manage the process ?
但问题是,我应该如何实现它在后台运行的程序,系统管理员很乐意设置并管理这个过程?
Some guys with far more experience than me, at golang-nuts, wrote, they don't use fork etc, and use some "wrapper" in form from monit etc.
一些比我经验丰富的家伙,在golang-nut写作,他们不使用叉子等,使用一些“包装”从monit等形式。
The target platform is Debian based, all other stuff on the box are init.d based.
目标平台是基于Debian的,框中的所有其他东西都是init。基于d。
Any good resources for that topic or sources of a well written example project ?
对于这个主题或编写良好的示例项目的源,有什么好的资源吗?
5 个解决方案
#1
24
As Nick mentioned Supervisord is a great option that has also worked well in my experience.
正如尼克所说,监督是一个很好的选择,在我的经验中也很有效。
Nick mentioned problems with forking- forking itself works fine AFAICT. The issue is not forking but dropping privileges. Due to the way the Go runtime starts the thread pool that goroutines are multiplexed over (when GOMAXPROX > 1), the setuid systemcall is not a reliable way to drop permissions.
Nick提到了forking- forking本身的问题。问题不是放弃特权,而是放弃特权。由于Go运行时启动goroutines多路复用的线程池的方式(当GOMAXPROX > 1时),setuid系统调用不是删除权限的可靠方法。
Instead, you should run your program as a non-privileged user and use the setcap utility to grant it the needed permissions.
相反,您应该以非特权用户的身份运行程序,并使用setcap实用程序授予它所需的权限。
For example, to allow binding to a low port number (like 80) run will need to run setcap once on the executable: sudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary
例如,要允许绑定到低端口号(比如80)运行,需要在可执行文件上运行一次setcap: sudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary
You may need to install setcap: sudo aptitude install libcap2-bin
您可能需要安装setcap: sudo aptitude install libcap2-bin
#2
16
There are already good answers but I will add some additional information.
已经有了很好的答案,但是我将添加一些额外的信息。
You do not need to install additional software such as supervisord
on Debian to take care of backgrounding the process.
您不需要安装额外的软件,如Debian上的monitor sord来处理后台进程。
Debian comes with a tool called start-stop-daemon
which is a standard way for starting daemons in init.d
scripts. It can also also put the process in background for you if the program does not do it on its own. Have a look at the --background
option.
Debian提供了一个名为start-stop-daemon的工具,这是在init中启动守护进程的标准方式。d脚本。如果程序本身不这样做,它也可以将进程放在后台。看看——后台选项。
Use /etc/init.d/skeleton
as the basis of your init script, but change the do_start()
function as follows:
使用/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
I also added the --make-pidfile
option which creates the PID file for you.
我还添加了-make-pidfile选项,它为您创建了PID文件。
In case you need to switch to a different user in a secure way, there is also --chuid
option.
如果您需要以一种安全的方式切换到另一个用户,还有——chuid选项。
On Ubuntu and RHEL/CentOS/SL 6.X the simplest way is to write an upstart
job configuration file. Just put exec /usr/sbin/yourprogram
in the /etc/init/yourprogram.conf
configuration file. With upstart there is no need to force the program in background. Do not add expect fork
or expect daemon
which you need with traditional daemons. With upstart it is better if the process does not fork.
在Ubuntu和RHEL/CentOS/SL 6上。最简单的方法是编写一个新的作业配置文件。把exec /usr/sbin/yourprogram放到/etc/init/yourprogram中。conf配置文件。对于upstart,不需要在后台强制程序。不要添加传统守护进程需要的expect fork或expect守护进程。对于upstart来说,如果流程不分叉就更好了。
#3
10
I wrote a blog post about this a while back. The idea of daemonizing seems wrong to me as it leaves you with a lot of other things to worry about (e.g. what happens when it fails? how do you manage a process restart? how do you handle logging, working directory, cores, system restart, etc...)
不久前我写了一篇关于这方面的博文。在我看来,自高自大的想法是错误的,因为它会让你担心很多其他的事情(例如,当它失败时会发生什么?)如何管理流程重新启动?如何处理日志记录、工作目录、核心、系统重启等……
Turns out, if you don't try to do all that, things get much easier.
事实证明,如果你不尝试去做这些,事情就会变得容易得多。
#4
5
Supervisord works really well for this in my experience.
根据我的经验,“监督”在这方面做得很好。
You write your app to run on the command line, print stuff etc and supervisord takes care of all the daemonising, restarting if it goes wrong, rate limiting etc, etc
你写你的应用程序运行在命令行上,打印东西等等,并且监督者负责所有的守护,如果它出错了重新启动,速率限制等等
I believe that forking go programs into the background in the traditional unix way is difficult because the runtime starts some threads before it runs your main()
routine
我认为,以传统的unix方式将程序放到后台是很困难的,因为运行时在运行main()例程之前启动一些线程
#5
2
But the question is, how should I implement my programm it runs in the background and it will be a pleasure for a system administrator to set it up and manage the process ?
但问题是,我应该如何实现它在后台运行的程序,系统管理员很乐意设置和管理这个过程?
A few thoughts here.
一些想法。
Provide packages and a repository
Installing a software is one thing, maintaining and running it is a totally different story. Sure, I can download a zip, unpack it, put the files into the proper directories (keep in mind that packages are usually scattered throughout the file system), create a system user to run the daemon, set the according permissions. But that's tedious, error prone (which will lead to a high influx of tickets like "Bah! Does not run! Fix it!") and hardly practical if the software is going to be installed on many systems.
安装软件是一回事,维护和运行软件则是另一回事。当然,我可以下载一个zip文件,解压它,将文件放到适当的目录中(记住,包通常分散在整个文件系统中),创建一个系统用户来运行守护进程,设置相应的权限。但这很乏味,容易出错(这会导致大量门票涌入,比如“呸!”)不跑!如果软件要安装在许多系统上,这几乎是不现实的。
So we need a package to lower the hurd of adoption. Providing a repository for those packages usually is no rocket science and makes installation and/or updates much easier. There is a difference between "Download->Distribute->Install/Update" and a single command/server like
所以我们需要一套方案来降低赫德的认可度。为这些包提供一个存储库通常不是什么复杂的事情,并且使安装和/或更新更容易。“下载->分发->安装/更新”和单个命令/服务器之间存在差异
$ awesomePm update coolApplication
Provide at least packages for RedHat and Debian based systems. Personally, I'd go for CentOS (which would make your package compatible to almost any RHEL derivate) and basic Debian. The latter should make it trivial to provide a package for Ubuntu, too. Since I don't use Debian or derivates any more, I am not too sure wether they are really compatible, there have been startup issues when I last built a .deb
.
至少为基于RedHat和Debian的系统提供包。就我个人而言,我会选择CentOS(这将使您的包与几乎所有RHEL派生产品兼容)和基本Debian。后者应该使为Ubuntu提供包变得微不足道。由于我不再使用Debian或派生类,所以我不太确定它们是否真的兼容,在我上次构建。deb时,有一些启动问题。
Provide proper documentation. Document what is installed, where, and why. Provide links to the according documentation. manpage references to dependencies are sufficient. This way, you enable even the most inexperienced admin to configure your package.
提供适当的文档。记录所安装的内容、位置和原因。提供相关文档的链接。对依赖项的manpage引用就足够了。这样,即使是最没有经验的管理员也可以配置您的包。
Use the most defensive, sane defaults.
使用最保守、最理智的默认值。
Special note with regard to golang: Most package build tools strip the binaries contained in the package by default. Go does not support that, so take care here.
关于golang的特别注意:大多数包构建工具会在默认情况下删除包中包含的二进制文件。Go不支持这个,所以在这里要小心。
Be complete
There is nothing more annoying than an incomplete package.
没有什么比一个不完整的包更烦人的了。
Use syslog if at all possible and adhere to it's conventions. This way, your logs will be put into places where the system admin expects them and they are taken care of if outdated automatically,preventing your application to cause disks running full. If the system admin wants special treatment of your application's logs, he will configure it this way.
如果可能的话,使用syslog,并遵守它的约定。这样,您的日志将被放置到系统管理员期望它们的位置,如果它们自动过期,则会得到处理,防止应用程序导致磁盘满负荷运行。如果系统管理员希望对应用程序的日志进行特殊处理,他将以这种方式配置它。
Do not rotate the logs via your application. It is the users choice on what to do with them (which might be relevant for their SLAs). Even if you make the way logs are rotated configurable, the admin has to learn how to configure it – which introduces unnecessary redundancy.
不要通过应用程序旋转日志。用户可以选择如何使用它们(这可能与他们的sla相关)。即使您使日志的旋转方式可配置,管理员也必须学习如何配置日志——这将引入不必要的冗余。
If you have to write to a log file, adhere to the target system's logging policy and provide a log rotate configuration file. You don't want you application be the cause of downtime just because the machine ran out of disk space, do you?
如果必须写入日志文件,请遵循目标系统的日志记录策略并提供日志旋转配置文件。您不希望您的应用程序仅仅因为机器耗尽了磁盘空间而导致停机,是吗?
Use system tools instead of reinventing the wheel. If your application needs to do some maintenance, do not bother to use a scheduler inside your application. Write a specialized tool for the maintenance (monolithic applications are so '00s) and utilize cron
. Specifically add according files to one of the /etc/cron*
directories.
使用系统工具而不是重新发明*。如果应用程序需要进行一些维护,请不要在应用程序中使用调度器。编写一个专用的维护工具(单片应用程序如此多)并使用cron。具体地将文件添加到/etc/cron*目录中的一个。
Provide proper init scripts! This way, the admin can use well known tools like systemctl
to mange startup and shutdown of your application. It is pretty annoying when you have to su
to a user or use sudo -u
to call a shell script on startup. Even when this script is called @onboot
, the deviation from standards is annoying. Just because a startup method works it does not mean that it should be used.
提供适当的init脚本!通过这种方式,管理员可以使用像systemctl这样的知名工具来管理应用程序的启动和关闭。当您必须向用户提供su或在启动时使用sudo -u调用shell脚本时,这是非常烦人的。甚至当这个脚本被称为@onboot时,偏离标准也是令人讨厌的。仅仅因为一个启动方法的工作,它并不意味着它应该被使用。
Bonus points for adding an SE-Linux profile!
添加一个SE-Linux配置文件的额外加分!
It should go without saying, but I have seen misconfigured packages way to often, so: Test your packages! Start with a minimal install of the target OS, install your package and make sure it runs as expected. Check every configuration you provide.
毫无疑问,我经常看到错误配置的包,所以:测试您的包!首先对目标操作系统进行最少的安装,然后安装您的包并确保它按预期运行。检查您提供的每个配置。
If you plan to have a package put into the official Debian repositories, you should plan some time: the reason why Debian is as stable is that the requirements on packages are pretty tight, and even when you fulfill all requirements, you have to go all the way from testing via unstable to stable.
如果你计划有一个官方Debian包放入存储库,你应该计划一些时间:Debian是稳定的原因是,要求包很紧,甚至当你满足所有的需求,你必须从测试通过不稳定的稳定。
Be precise
Do not use existing users just because it is convenient. If you create a web application, do not reuse the "apache" or "www" user. Create a user dedicated to your package and add this user to the according groups.
不要仅仅因为方便就使用现有用户。如果您创建了一个web应用程序,不要重用“apache”或“www”用户。创建一个专门用于包的用户,并将该用户添加到根据组。
Adhere to the principle of least necessary permissions. There is hardly a reason to have a binary world executable, much less world writable (which would be an extreme security hole). What you often see here on SO if an application does not run is the suggestion to set the permissions to [0]777, which allows every user to make modifications whatsoever on the file. Actually, there is almost no reason to make a binary writable to any user: root, who does the updates anyway, can always write anything. So the permissions should be 0550
for binaries. The principle also applies to data directories and such. Invest some time and effort here. You don't want your app to be the vector for an successful attack, do you? Even potential security risks tend to fire back on you and your reputation. What I tend to do is to set all data files to 0600
for files that need to be written by the system user of the application, 0400
for read-only files and 0500
for binaries. Then, I do a granular analysis what the group permissions should be. For example: A group might change the individual templates for a web application – but most likely not the directory structure of the resource directory subtree.
遵循最少必要权限的原则。几乎没有理由让二进制世界可执行,更不用说世界可写(这将是一个极端的安全漏洞)。您在这里经常看到的是,如果应用程序不运行,建议将权限设置为[0]777,这样每个用户都可以对文件进行任何修改。实际上,几乎没有理由为任何用户创建一个二进制可写的:root用户可以编写任何内容。所以二进制文件的权限应该是0550。该原则也适用于数据目录。在这里投入一些时间和精力。你不希望你的应用成为成功攻击的媒介,是吗?即使是潜在的安全风险也会对你和你的名誉造成伤害。我倾向于将需要由应用程序的系统用户编写的所有数据文件设置为0600,只读文件设置为0400,二进制文件设置为0500。然后,我对组权限应该是什么进行了细粒度分析。例如:一个组可能会更改web应用程序的单个模板——但很可能不会更改资源目录子树的目录结构。
If you put effort into security, you will increase trust. Be aware that packages are often checked for their security impact prior to the decision wether they are adopted.
如果你把精力放在安全上,你会增加信任。请注意,在决定是否采用包之前,通常会检查包的安全性影响。
Adhere to the FHS(!!)! And even then: just because you can do anything under /opt/yourapplication
, it is not always a good idea to do so. Rather install into /usr
and /var
respectively (assuming your application is not necessary during boot time).
坚持FHS(! !)!即便如此:仅仅因为您可以在/opt/yourapplication下执行任何操作,那么这样做并不总是一个好主意。分别安装到/usr和/var(假设在引导期间不需要应用程序)。
If you have dependencies, define them. Do not merely assume that a package is present.
如果您有依赖项,请定义它们。不要仅仅假设包存在。
If you have a dependency for a local SMTP server, do not declare a dependency on postfix
. Maybe the admin prefers sendmail (for whatever reason that may be). So define a dependency on mail-transport-agent
(Debian) or mta
(RH, iirc) instead.
如果您对本地SMTP服务器有依赖项,请不要声明对postfix的依赖项。也许管理员更喜欢sendmail(不管出于什么原因)。因此,定义对邮件传输代理(Debian)或mta (RH, iirc)的依赖关系。
Conclusion
This is what I expect of a good software – integrating nicely with existing software and to make it easy to install, maintain, configure and run it without having to learn redundant configuration. If I see a SELinux profile for a package, that really gives the vendor a bonus – unless the profile is extremely sloppy, it shows that the vendor takes security very serious.
这就是我对优秀软件的期望——与现有软件很好地集成,并使其易于安装、维护、配置和运行,而无需学习冗余配置。如果我看到一个包的SELinux配置文件,这确实会给供应商带来好处——除非这个配置文件非常草率,这表明供应商非常重视安全性。
#1
24
As Nick mentioned Supervisord is a great option that has also worked well in my experience.
正如尼克所说,监督是一个很好的选择,在我的经验中也很有效。
Nick mentioned problems with forking- forking itself works fine AFAICT. The issue is not forking but dropping privileges. Due to the way the Go runtime starts the thread pool that goroutines are multiplexed over (when GOMAXPROX > 1), the setuid systemcall is not a reliable way to drop permissions.
Nick提到了forking- forking本身的问题。问题不是放弃特权,而是放弃特权。由于Go运行时启动goroutines多路复用的线程池的方式(当GOMAXPROX > 1时),setuid系统调用不是删除权限的可靠方法。
Instead, you should run your program as a non-privileged user and use the setcap utility to grant it the needed permissions.
相反,您应该以非特权用户的身份运行程序,并使用setcap实用程序授予它所需的权限。
For example, to allow binding to a low port number (like 80) run will need to run setcap once on the executable: sudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary
例如,要允许绑定到低端口号(比如80)运行,需要在可执行文件上运行一次setcap: sudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary
You may need to install setcap: sudo aptitude install libcap2-bin
您可能需要安装setcap: sudo aptitude install libcap2-bin
#2
16
There are already good answers but I will add some additional information.
已经有了很好的答案,但是我将添加一些额外的信息。
You do not need to install additional software such as supervisord
on Debian to take care of backgrounding the process.
您不需要安装额外的软件,如Debian上的monitor sord来处理后台进程。
Debian comes with a tool called start-stop-daemon
which is a standard way for starting daemons in init.d
scripts. It can also also put the process in background for you if the program does not do it on its own. Have a look at the --background
option.
Debian提供了一个名为start-stop-daemon的工具,这是在init中启动守护进程的标准方式。d脚本。如果程序本身不这样做,它也可以将进程放在后台。看看——后台选项。
Use /etc/init.d/skeleton
as the basis of your init script, but change the do_start()
function as follows:
使用/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
I also added the --make-pidfile
option which creates the PID file for you.
我还添加了-make-pidfile选项,它为您创建了PID文件。
In case you need to switch to a different user in a secure way, there is also --chuid
option.
如果您需要以一种安全的方式切换到另一个用户,还有——chuid选项。
On Ubuntu and RHEL/CentOS/SL 6.X the simplest way is to write an upstart
job configuration file. Just put exec /usr/sbin/yourprogram
in the /etc/init/yourprogram.conf
configuration file. With upstart there is no need to force the program in background. Do not add expect fork
or expect daemon
which you need with traditional daemons. With upstart it is better if the process does not fork.
在Ubuntu和RHEL/CentOS/SL 6上。最简单的方法是编写一个新的作业配置文件。把exec /usr/sbin/yourprogram放到/etc/init/yourprogram中。conf配置文件。对于upstart,不需要在后台强制程序。不要添加传统守护进程需要的expect fork或expect守护进程。对于upstart来说,如果流程不分叉就更好了。
#3
10
I wrote a blog post about this a while back. The idea of daemonizing seems wrong to me as it leaves you with a lot of other things to worry about (e.g. what happens when it fails? how do you manage a process restart? how do you handle logging, working directory, cores, system restart, etc...)
不久前我写了一篇关于这方面的博文。在我看来,自高自大的想法是错误的,因为它会让你担心很多其他的事情(例如,当它失败时会发生什么?)如何管理流程重新启动?如何处理日志记录、工作目录、核心、系统重启等……
Turns out, if you don't try to do all that, things get much easier.
事实证明,如果你不尝试去做这些,事情就会变得容易得多。
#4
5
Supervisord works really well for this in my experience.
根据我的经验,“监督”在这方面做得很好。
You write your app to run on the command line, print stuff etc and supervisord takes care of all the daemonising, restarting if it goes wrong, rate limiting etc, etc
你写你的应用程序运行在命令行上,打印东西等等,并且监督者负责所有的守护,如果它出错了重新启动,速率限制等等
I believe that forking go programs into the background in the traditional unix way is difficult because the runtime starts some threads before it runs your main()
routine
我认为,以传统的unix方式将程序放到后台是很困难的,因为运行时在运行main()例程之前启动一些线程
#5
2
But the question is, how should I implement my programm it runs in the background and it will be a pleasure for a system administrator to set it up and manage the process ?
但问题是,我应该如何实现它在后台运行的程序,系统管理员很乐意设置和管理这个过程?
A few thoughts here.
一些想法。
Provide packages and a repository
Installing a software is one thing, maintaining and running it is a totally different story. Sure, I can download a zip, unpack it, put the files into the proper directories (keep in mind that packages are usually scattered throughout the file system), create a system user to run the daemon, set the according permissions. But that's tedious, error prone (which will lead to a high influx of tickets like "Bah! Does not run! Fix it!") and hardly practical if the software is going to be installed on many systems.
安装软件是一回事,维护和运行软件则是另一回事。当然,我可以下载一个zip文件,解压它,将文件放到适当的目录中(记住,包通常分散在整个文件系统中),创建一个系统用户来运行守护进程,设置相应的权限。但这很乏味,容易出错(这会导致大量门票涌入,比如“呸!”)不跑!如果软件要安装在许多系统上,这几乎是不现实的。
So we need a package to lower the hurd of adoption. Providing a repository for those packages usually is no rocket science and makes installation and/or updates much easier. There is a difference between "Download->Distribute->Install/Update" and a single command/server like
所以我们需要一套方案来降低赫德的认可度。为这些包提供一个存储库通常不是什么复杂的事情,并且使安装和/或更新更容易。“下载->分发->安装/更新”和单个命令/服务器之间存在差异
$ awesomePm update coolApplication
Provide at least packages for RedHat and Debian based systems. Personally, I'd go for CentOS (which would make your package compatible to almost any RHEL derivate) and basic Debian. The latter should make it trivial to provide a package for Ubuntu, too. Since I don't use Debian or derivates any more, I am not too sure wether they are really compatible, there have been startup issues when I last built a .deb
.
至少为基于RedHat和Debian的系统提供包。就我个人而言,我会选择CentOS(这将使您的包与几乎所有RHEL派生产品兼容)和基本Debian。后者应该使为Ubuntu提供包变得微不足道。由于我不再使用Debian或派生类,所以我不太确定它们是否真的兼容,在我上次构建。deb时,有一些启动问题。
Provide proper documentation. Document what is installed, where, and why. Provide links to the according documentation. manpage references to dependencies are sufficient. This way, you enable even the most inexperienced admin to configure your package.
提供适当的文档。记录所安装的内容、位置和原因。提供相关文档的链接。对依赖项的manpage引用就足够了。这样,即使是最没有经验的管理员也可以配置您的包。
Use the most defensive, sane defaults.
使用最保守、最理智的默认值。
Special note with regard to golang: Most package build tools strip the binaries contained in the package by default. Go does not support that, so take care here.
关于golang的特别注意:大多数包构建工具会在默认情况下删除包中包含的二进制文件。Go不支持这个,所以在这里要小心。
Be complete
There is nothing more annoying than an incomplete package.
没有什么比一个不完整的包更烦人的了。
Use syslog if at all possible and adhere to it's conventions. This way, your logs will be put into places where the system admin expects them and they are taken care of if outdated automatically,preventing your application to cause disks running full. If the system admin wants special treatment of your application's logs, he will configure it this way.
如果可能的话,使用syslog,并遵守它的约定。这样,您的日志将被放置到系统管理员期望它们的位置,如果它们自动过期,则会得到处理,防止应用程序导致磁盘满负荷运行。如果系统管理员希望对应用程序的日志进行特殊处理,他将以这种方式配置它。
Do not rotate the logs via your application. It is the users choice on what to do with them (which might be relevant for their SLAs). Even if you make the way logs are rotated configurable, the admin has to learn how to configure it – which introduces unnecessary redundancy.
不要通过应用程序旋转日志。用户可以选择如何使用它们(这可能与他们的sla相关)。即使您使日志的旋转方式可配置,管理员也必须学习如何配置日志——这将引入不必要的冗余。
If you have to write to a log file, adhere to the target system's logging policy and provide a log rotate configuration file. You don't want you application be the cause of downtime just because the machine ran out of disk space, do you?
如果必须写入日志文件,请遵循目标系统的日志记录策略并提供日志旋转配置文件。您不希望您的应用程序仅仅因为机器耗尽了磁盘空间而导致停机,是吗?
Use system tools instead of reinventing the wheel. If your application needs to do some maintenance, do not bother to use a scheduler inside your application. Write a specialized tool for the maintenance (monolithic applications are so '00s) and utilize cron
. Specifically add according files to one of the /etc/cron*
directories.
使用系统工具而不是重新发明*。如果应用程序需要进行一些维护,请不要在应用程序中使用调度器。编写一个专用的维护工具(单片应用程序如此多)并使用cron。具体地将文件添加到/etc/cron*目录中的一个。
Provide proper init scripts! This way, the admin can use well known tools like systemctl
to mange startup and shutdown of your application. It is pretty annoying when you have to su
to a user or use sudo -u
to call a shell script on startup. Even when this script is called @onboot
, the deviation from standards is annoying. Just because a startup method works it does not mean that it should be used.
提供适当的init脚本!通过这种方式,管理员可以使用像systemctl这样的知名工具来管理应用程序的启动和关闭。当您必须向用户提供su或在启动时使用sudo -u调用shell脚本时,这是非常烦人的。甚至当这个脚本被称为@onboot时,偏离标准也是令人讨厌的。仅仅因为一个启动方法的工作,它并不意味着它应该被使用。
Bonus points for adding an SE-Linux profile!
添加一个SE-Linux配置文件的额外加分!
It should go without saying, but I have seen misconfigured packages way to often, so: Test your packages! Start with a minimal install of the target OS, install your package and make sure it runs as expected. Check every configuration you provide.
毫无疑问,我经常看到错误配置的包,所以:测试您的包!首先对目标操作系统进行最少的安装,然后安装您的包并确保它按预期运行。检查您提供的每个配置。
If you plan to have a package put into the official Debian repositories, you should plan some time: the reason why Debian is as stable is that the requirements on packages are pretty tight, and even when you fulfill all requirements, you have to go all the way from testing via unstable to stable.
如果你计划有一个官方Debian包放入存储库,你应该计划一些时间:Debian是稳定的原因是,要求包很紧,甚至当你满足所有的需求,你必须从测试通过不稳定的稳定。
Be precise
Do not use existing users just because it is convenient. If you create a web application, do not reuse the "apache" or "www" user. Create a user dedicated to your package and add this user to the according groups.
不要仅仅因为方便就使用现有用户。如果您创建了一个web应用程序,不要重用“apache”或“www”用户。创建一个专门用于包的用户,并将该用户添加到根据组。
Adhere to the principle of least necessary permissions. There is hardly a reason to have a binary world executable, much less world writable (which would be an extreme security hole). What you often see here on SO if an application does not run is the suggestion to set the permissions to [0]777, which allows every user to make modifications whatsoever on the file. Actually, there is almost no reason to make a binary writable to any user: root, who does the updates anyway, can always write anything. So the permissions should be 0550
for binaries. The principle also applies to data directories and such. Invest some time and effort here. You don't want your app to be the vector for an successful attack, do you? Even potential security risks tend to fire back on you and your reputation. What I tend to do is to set all data files to 0600
for files that need to be written by the system user of the application, 0400
for read-only files and 0500
for binaries. Then, I do a granular analysis what the group permissions should be. For example: A group might change the individual templates for a web application – but most likely not the directory structure of the resource directory subtree.
遵循最少必要权限的原则。几乎没有理由让二进制世界可执行,更不用说世界可写(这将是一个极端的安全漏洞)。您在这里经常看到的是,如果应用程序不运行,建议将权限设置为[0]777,这样每个用户都可以对文件进行任何修改。实际上,几乎没有理由为任何用户创建一个二进制可写的:root用户可以编写任何内容。所以二进制文件的权限应该是0550。该原则也适用于数据目录。在这里投入一些时间和精力。你不希望你的应用成为成功攻击的媒介,是吗?即使是潜在的安全风险也会对你和你的名誉造成伤害。我倾向于将需要由应用程序的系统用户编写的所有数据文件设置为0600,只读文件设置为0400,二进制文件设置为0500。然后,我对组权限应该是什么进行了细粒度分析。例如:一个组可能会更改web应用程序的单个模板——但很可能不会更改资源目录子树的目录结构。
If you put effort into security, you will increase trust. Be aware that packages are often checked for their security impact prior to the decision wether they are adopted.
如果你把精力放在安全上,你会增加信任。请注意,在决定是否采用包之前,通常会检查包的安全性影响。
Adhere to the FHS(!!)! And even then: just because you can do anything under /opt/yourapplication
, it is not always a good idea to do so. Rather install into /usr
and /var
respectively (assuming your application is not necessary during boot time).
坚持FHS(! !)!即便如此:仅仅因为您可以在/opt/yourapplication下执行任何操作,那么这样做并不总是一个好主意。分别安装到/usr和/var(假设在引导期间不需要应用程序)。
If you have dependencies, define them. Do not merely assume that a package is present.
如果您有依赖项,请定义它们。不要仅仅假设包存在。
If you have a dependency for a local SMTP server, do not declare a dependency on postfix
. Maybe the admin prefers sendmail (for whatever reason that may be). So define a dependency on mail-transport-agent
(Debian) or mta
(RH, iirc) instead.
如果您对本地SMTP服务器有依赖项,请不要声明对postfix的依赖项。也许管理员更喜欢sendmail(不管出于什么原因)。因此,定义对邮件传输代理(Debian)或mta (RH, iirc)的依赖关系。
Conclusion
This is what I expect of a good software – integrating nicely with existing software and to make it easy to install, maintain, configure and run it without having to learn redundant configuration. If I see a SELinux profile for a package, that really gives the vendor a bonus – unless the profile is extremely sloppy, it shows that the vendor takes security very serious.
这就是我对优秀软件的期望——与现有软件很好地集成,并使其易于安装、维护、配置和运行,而无需学习冗余配置。如果我看到一个包的SELinux配置文件,这确实会给供应商带来好处——除非这个配置文件非常草率,这表明供应商非常重视安全性。