英文:
Exec.Command Interrupt
问题
我正在编写一个应用程序,它将作为一个守护进程在Ubuntu 14.04上运行。这个守护进程的目的是运行一个for循环,检查各种数据库表中是否有数据,如果有数据,则会生成一个goroutine来对各种数据执行各种操作。这样做是为了让我可以更频繁地执行任务,而不仅仅是cron允许我调度任务的频率。
一个例子是,如果守护进程在数据库表"notifications"中发现了一行新数据,它将生成一个新的goroutine,直到完成为止,这意味着运行以下命令:
err := exec.Command("sh","-c","php /var/app/send_notification.php").Run()
是的,我需要从Go中执行一些PHP脚本。目前我没有时间将所有的PHP代码重写为Go,所以我必须想办法让它工作。
我已经成功编写了守护进程,如果收到SIGINT信号,它将进行一个基本上优雅的关闭。它将让所有的goroutine完成它们的任务,以确保没有工作被中途停止,这可能会导致问题。
问题是,一旦将SIGINT信号发送给这个守护进程,由exec.Command()启动的任何进程都会立即中止。
上面的链接是我用作这个守护进程模板的参考。
所以我的问题是:当守护进程接收到SIGINT时,有没有办法让在goroutine中启动的exec.Command()运行直到完成?如果没有,是否有其他方法可以在守护进程接收到SIGINT后执行命令并允许其运行直到完成?
英文:
I'm writing an application that will run as a daemon on ubuntu 14.04. The purpose of this daemon is to run a for loop that will check for data in various database tables and if data is present it will spawn a goroutine to take various actions on various data. This is done to allow me doing tasks more often than cron allows me to schedule tasks.
An example would be if the daemon found a new row in the database table "notifications" it would spawn a new goroutine that would run until it's done, which in this case would mean running the command below:
err := exec.Command("sh","-c","php /var/app/send_notification.php").Run()
Yes. I've the need to execute some php scripts from go. I don't have the time allotted to rewrite all the php code in go just yet so I'll have to make this work somehow.
I've managed to write the daemon so it will do a mostly graceful shutdown if SIGINT is sent to it. It will let all goroutines complete their tasks so that no work is stopped halfway through which may end up causing problems.
The problem is now that as soon as SIGINT is sent to this daemon, any and all processes started by the exec.Command() is aborted right away.
http://rcrowley.org/articles/golang-graceful-stop.html
The link above is what I've used as a template for this daemon.
So my question is: Is there any way to allow an exec.Command() started in a goroutine to run until completion when the daemon receives SIGINT? If not, is there another way to go about executing a command from go and allowing it to run until completion after SIGINT is received by the daemon?
答案1
得分: 2
新创建的进程将与您的守护进程在同一个进程组中。
这意味着默认情况下,发送给您的守护进程的信号将广播到您创建的进程。
您可以在命令之前使用Cmd
类型的SysProcAttr
属性,强制将新创建的进程置于其自己的进程组中。
cmd := exec.Command("sh", "-c", "php /var/app/send_notification.php")
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
error := cmd.Run()
英文:
The newly created process will be on the same process group than your daemon.
This means that by default, signal sent to your daemon will be broadcast to your created processes.
You can force your newly created process to be in his own process group just before the command using the SysProcAttr
attribute of the Cmd
type.
cmd := exec.Command("sh","-c","php /var/app/send_notification.php")
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid:true}
error := cmd.Run()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论