如何让我的Golang Web服务器在后台运行?

52

我最近完成了Wiki web开发教程 (http://golang.org/doc/articles/wiki/)。我非常喜欢,想要更多地尝试net/http包。

然而,当我从控制台运行wiki时,它会接管控制台。如果我关闭终端或使用 CTRL+Z 停止进程,则服务器将停止。

我该如何让服务器在后台运行?我认为这个术语是以守护进程方式运行。

我在Ubuntu 12.04上运行。谢谢任何帮助。

6个回答

69

首先,简单易用的东西

如果你想要一个启动脚本而不需要太多努力(也就是处理过程,只需由系统管理),你可以创建一个 systemd 服务。具体如何操作请参考Greg's answer。 之后,你可以使用以下命令启动服务:

systemctl start myserver

以前我会建议尝试使用xinetd或类似的东西来实现更精细的资源和权限管理,但是systemd已经覆盖了这一点

使用shell

您可以像这样启动进程:

nohup ./myexecutable &
&在shell中表示将命令放到后台执行,并将其保留在作业列表中。 在某些shell中,如果父shell使用HANGUP信号退出,则作业将被终止。 为了防止这种情况,您可以使用nohup命令启动命令,该命令会丢弃HANGUP信号。 然而,如果被调用的进程重新连接HANGUP信号,则此方法不起作用。 要确保安全,您需要将进程从shell的作业列表中删除。对于两个著名的shell,请按以下方式操作: bash:
./myexecutable &
disown <pid>

zsh:

->

zsh:

./myexecutable &!

结束后台任务

通常,shell会打印进程的PID,然后可以使用kill命令来停止服务器。如果您的shell没有打印PID,则可以使用以下方法获取:

echo $!

直接在执行后。这会打印出分叉进程的PID。


那么我该如何返回并停止它,或重新启动? - quakkels
5
在关闭终端时,& 会继续运行命令(取决于您使用的shell)。在bash中,您需要在使用&ctrl+Z将其放入后台后,使用screennohupdisown命令。 - lunixbochs
@lunixbochs,你可能不依赖于shell在这方面的行为是正确的。我会更新我的答案。 - nemo
谢谢您提供如此详细的答案!我可以看出,如果您在启动后台进程时忘记记录PID,像upstart这样的程序会非常方便。我将尝试使用这两种技术并回报结果。 - quakkels
我刚刚在Bash版本5.0.17(1)-release中尝试了&!,而且它可以工作。 - Orestis Kapar

9

Monit是另一个选择。 - jemeshsu

6

Ubuntu?使用upstart

/etc/init创建一个名为your-service-name.conf的文件以配置您的作业。

start on net-device-up
exec /path/to/file --option

您可以使用start your-service-name命令,以及:stoprestartstatus命令。


3
Upstart似乎已经被systemd取代了,是吗?在Ubuntu LTS 14.04上现在该怎么做? - Carmageddon
sudo service start your-service-name 不起作用,找不到服务。 - Alston

5
这将使用 systemd 配置您的服务,不是全面的教程,而是快速入门如何设置。 app.service 文件的内容。
[Unit]  
Description=deploy-webhook service
After=network.target

[Service]      
ExecStart=/usr/bin/go webhook.go    
WorkingDirectory=/etc/deploy-webhook

User=app-svc      
Group=app-svc

Restart=always    
RestartSec=10    
KillSignal=SIGINT

SyslogIdentifier=deploy-webhook-service      
PrivateTmp=true  

Environment=APP_PARAM_1=ParamA
Environment=APP_PARAM_2=ParamB

[Install]      
WantedBy=multi-user.target  

启动服务

sudo systemctl start deploy-webhook.service

服务状态

sudo systemctl status deploy-webhook.service

日志

journalctl -u deploy-webhook -e

1

当你按下ctrl+z(将当前任务挂起)后,你可以在终端中运行命令bg(代表后台)让最新的任务在后台继续运行。

当需要时,运行fg回到任务。

为了达到相同的效果,你可以在命令的末尾加上&以在后台启动它。


0

补充Greg的答案:

要将Go应用程序作为服务运行,您需要创建一个新的服务单元文件。

但是,该应用程序需要知道Go安装的位置。查找该位置的最简单方法是运行此命令:

which go

这会给你一个像这样的输出:

/usr/local/go/bin/go

有了这些信息,您可以创建systemd服务文件。使用以下命令在/etc/systemd/system/中创建名为providus-app.service的文件:

sudo touch /etc/systemd/system/providus-app.service

接下来打开新创建的文件:

sudo nano /etc/systemd/system/providus-app.service

将以下配置粘贴到您的服务文件中:
[Unit]
Description=Providus App Service
After=network.target

[Service]
Type=forking

User=deploy
Group=deploy

ExecStart=/usr/local/go/bin/go run main.go
WorkingDirectory=/home/deploy/providus-app

Restart=always
RestartSec=10
KillSignal=SIGINT

SyslogIdentifier=providus-app-service
PrivateTmp=true

[Install]
WantedBy=multi-user.target

当你完成后,保存并关闭文件。

接下来,重新加载systemd守护进程,以便它知道我们的服务文件:

sudo systemctl daemon-reload

通过输入以下命令启动Providus应用程序服务:

sudo systemctl restart providus-app

请仔细检查是否出现错误,输入以下命令:

sudo systemctl status providus-app

然后启用Providus应用程序服务文件,使得Providus应用程序可以在系统启动时自动启动,即每当服务器重新启动时可以自行启动:

sudo systemctl enable providus-app

这将在/etc/systemd/system/multi-user.target.wants/providus-app.service中创建一个multi-user.target符号链接,用于您创建的/etc/systemd/system/providus-app.service文件。
要检查日志:
sudo journalctl -u providus-app

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接