为了将定期的天气更新导入到我的 Redis 数据库中,我尝试使用的方案如下
我有一个 PHP 脚本,可以从相关的天气 API 获取天气信息。它如下所示
<?php
function getWeather()
{
if (weatherupdaterequired)
{
//weather API call
//parse and store to database
}
}
while (true)
{
getWeather();
sleep(30);
}
?>
它存储在我的/usr/local/bin
文件夹中。在同一个文件夹中,我有一个 shell 脚本,runweather
它的作用是:
#!/bin/sh
nohup php /usr/local/bin/echoweather.php >/dev/null 2>&1 &
我通常倾向于使用#!/bin/bash
,但在这种情况下,我发现只有在启动时运行(如下所示)才#!/bin/sh
有效。我认为这与 bash shell 尚不可用有关。
然后我创建了一个符号链接到runweather
ln -s /usr/local/bin/runweather /etc/init.d/runweather
然后是另一个符号链接
ln -s /etc/init.d/runweather /etc/rc2.d/S99runweather
一些解释性说明
- 它
/usr/local/bin/echoweather.php
正在做所有实际工作。它以 30 秒为间隔运行,不工作时处于休眠状态 - 在每次终止运行之前,它会放置一个临时的 Redis 键
$redis-
setEx("weatherreport",29,$echoCount)`,我可以使用它来监控它的运行状况 echoweather.php
将启动时运行的shell 脚本放入中/usr/local/bin
,然后将其符号链接到 中,/etc/init.d
然后再将其符号链接到 中,这/etc/rc2.d
可能看起来很复杂。我这样做是因为我发现,如果我将实际的 shell 脚本放入 中/etc/init.d
,然后将其符号链接到 中,/etc/rc2.d
它不会执行。
这个方案很有效。我重启了几次服务器,并通过 redis-cli 在 Redis 中echoweather.php
查找weatherreport
密钥来检查其运行状况 - 始终存在且正确。但是,在处理 Ubuntu 启动脚本方面,我是个业余爱好者。也许有更简单的方法可以做这些事情?如果有人能发表评论,我将不胜感激。
答案1
如果您没有运行 Ubuntu 的 EOL 版本,您的 init 系统已经基于 systemd,因此使用它是正确的选择。有些人可能会告诉您将其用于Type=idle
您的服务单元,但请:(来自systemd 手册页):
请注意,使用除 simple 之外的任何其他类型都可能延迟启动过程,因为服务管理器需要等待服务初始化完成。因此建议不要不必要地使用除 simple 之外的任何其他类型。(另请注意,通常不建议对长时间运行的服务使用 idle 或 oneshot。)
考虑到这一点,我们应该通过设置目标和依赖关系来管理我们的服务排序。脚本要正常工作至少需要满足三个重要要求:
- 您的网络堆栈需要正常运行;
- 您的脚本应该在启动过程的后期运行,并且;
- 您的脚本应该在 Redis 完全启动后运行。
确定了这些要求后,让我们来看看systemd 目标所以我们知道我们想要什么,需要什么,应该依赖什么或等待什么:
- 严格需要配置网络连接的单元应该拉入
network-online.target
,因此我们的单元Wants
这个并且应该只运行After
这个目标; multi-user.target
设置一个多用户系统,并在完成所有需要的操作后完成,因此单元可能Wants
就是WantedBy
这样。由于我们确实希望我们的单元在引导过程的后期运行,因此运行After
这个目标也是我们想要的;- Redis 是我们正在配置的多用户系统的一部分,并且我们的单元只有在 Redis 启动并运行时才能产生其预期的效果,因此
Requires
Redis 必须运行,我们才应该加载After
它。
考虑到这一点,我们可以将所有这些都考虑echoweather.service
进去写入一个文件:/etc/systemd/system/
[Unit]
Description=Gets regular weather updates into my Redis database
Wants=network-online.target multi-user.target
Requires=redis-server.service
After=network-online.target multi-user.target redis-server.service
[Service]
PIDFile=/var/run/echoweather.pid
ExecStart=/usr/bin/php /usr/local/bin/echoweather.php >/dev/null 2>&1 &
Type=forking
KillMode=process
[Install]
WantedBy=multi-user.target
完成后,重新加载守护程序文件,启用服务单元并运行进程:
$ sudo systemctl daemon-reload
$ sudo systemctl enable echoweather.service
$ sudo systemctl start echoweather.service