www61616 发表于 2021-5-20 17:34:11

systemd.unit无法执行具有while循环的脚本?

先贴代码(整个脚本):
(在线剪贴板)
https://paste.ubuntu.com/p/S5mxS5GNHg/

问题:(脚本33-55行)函数中有while循环以及多个if判断语句,将该脚本作为启动命令写入systemd.unit但无法启动;若将while循环以及只保留一个if判断语句,则该systemd.unit可以启动成功。

我的分析:systemd.uniut本身带有进程守护,脚本中带有判断条件,造成systemd判断条件重复,因此无需要给到systemd判断条件,只需为其明确执行的指令即可?

该systemd.unit写法:

[*]
[*]Description=rocketmq
[*]After=network.target
[*]
[*]
[*]User=root
[*]Type=forking
[*]ExecStart=/opt/rocketmq-4.8.0/mqinit2 start
[*]ExecStop=/opt/rocketmq-4.8.0/mqinit2 stop
[*]ExecReload=/opt/rocketmq-4.8.0/mqinit2 restart
[*]Restart=on-failure
[*]RestartSec=6
[*]LimitNOFILE=65536
[*]
[*]
[*]
[*]WantedBy=multi-user.target复制代码

执行systemctl start rocketmq,却超时了:

Job for rocketmq.service failed because a timeout was exceeded. See "systemctl status rocketmq.service" and "journalctl -xe" for details.

执行失败的代码(有while循环):
[*]function start_broker() {
[*]while true
[*]do
[*]get_broker_pid
[*]if [[ -n ${BROKER_PID} ]]; then
[*]echo -e "\033[1;42;37m +++ The RocketMQ_broker(${BROKER_PID}) is already exsit... \033[0m"
[*]break
[*]else
[*]cd ${ROCKETMQ_BIN} || exit
[*]nohup sh mqbroker -c ${CONF_DIR} -n ${ADDR}:${NAMESRV_PORT} > ${BROKER_RUN_LOG} 2>&1 &
[*]sleep 1
[*]#重新获取PID
[*]get_broker_pid
[*]if [[ -z ${BROKER_PID} ]]; then
[*]echo -e "\033[1;41;37m *** The RocketMQ_broker boot Faild!! \033[0m"
[*]else
[*]echo -e "\033[1;42;37m ### The RocketMQ_broker(${BROKER_PID}) boot successfully!! \033[0m"
[*]break
[*]fi
[*]fi
[*]done
[*]}复制代码

看了下日志,都是满足了我写的if判断中变量为空值时的输出,并且时间间隔都是写好的休眠时间 sleep 1:
[*]May 20 15:55:51 hyd021_dev-middleware-1 mqinit2:*** The RocketMQ_namesrv boot Faild!!
[*]May 20 15:55:52 hyd021_dev-middleware-1 mqinit2:*** The RocketMQ_namesrv boot Faild!!
[*]May 20 15:55:53 hyd021_dev-middleware-1 mqinit2:*** The RocketMQ_namesrv boot Faild!!
[*]May 20 15:55:54 hyd021_dev-middleware-1 mqinit2:*** The RocketMQ_namesrv boot Faild!!
[*]May 20 15:55:55 hyd021_dev-middleware-1 mqinit2:*** The RocketMQ_namesrv boot Faild!!复制代码

并且我将while循环部分全部去掉,仍然启动失败,最后我只保留了一个if语句,则能够启动成功
能够执行成功的代码:

[*]function start_broker() {
[*]cd ${ROCKETMQ_BIN} || exit
[*]nohup sh mqbroker -c ${CONF_DIR} -n ${ADDR}:${NAMESRV_PORT} > ${BROKER_RUN_LOG} 2>&1 &
[*]sleep 2
[*]#重新获取PID
[*]get_broker_pid
[*]if [[ -z ${BROKER_PID} ]]; then
[*]echo -e "\033[1;41;37m *** The RocketMQ_broker boot Faild!! \033[0m"
[*]else
[*]echo -e "\033[1;42;37m ### The RocketMQ_broker(${BROKER_PID}) boot successfully!! \033[0m"
[*]fi
[*]}复制代码

求解惑,谢谢!

@G.K.D

G.K.D 发表于 2021-5-20 17:41:34

本帖最后由 G.K.D 于 2021-5-20 17:44 编辑

等我一下,我看看代码,不过我对 systemd 不是很熟。。。

www61616 发表于 2021-5-20 17:46:59


G.K.D 发表于 2021-5-20 17:41

等我一下,我看看代码,不过我对 systemd 不是很熟。。。
哦豁,大佬回复得真快。我已经对脚本进行测试,功能都正常,但是写进systemd.unit就扑该了。。

G.K.D 发表于 2021-5-20 17:41:00

你用 systemctl 命令无法启动,那你直接运行这个脚本去启动,正常吗?

我这刚回复,你就回复我了。。。

G.K.D 发表于 2021-5-20 17:47:38

本帖最后由 G.K.D 于 2021-5-20 18:26 编辑

你看过这个 ${BROKER_RUN_LOG} 程序日志没有,有没有启动失败的原因。

---

我对 systemd 不太熟,所以下面这些仅供参考~

---

我看了一圈,首先你这个循环是完全没必要的。


其次,systemd 是会自己判断进程是否已运行(运行后会记录进程信息,用来检查、停止、守护进程等)。
以前流行的 init.d 服务管理方式是系统只负责启动,启动成功与否等问题都不管,因此需要自己写很长很复杂的服务管理脚本。
而现在 systemd 就是为了解决这个痛点,因此很多情况都由 systemd 自己处理了,不再需要自己写很长很长的服务脚本了。

所以你没必要启动前判断进程是否存在,因为 systemd 会替你判断。


另外,我记得 systemd 本来就是后台启动的,你脚本里加上 nohup 就有点作用重复了。。。

www61616 发表于 2021-5-20 17:54:51


G.K.D 发表于 2021-5-20 17:54

你看过这个 ${BROKER_RUN_LOG} 程序日志没有,有没有启动失败的原因。

---
大哥,研究了两天,我(可能)知道原因了,似乎是脚本中必须要声明变量。
比如我这个是启java的应用,我在脚本中声明好java的环境变量,这个systemd就跑得起来了(尽管/etc/profile中已经声明了Java变量)。
完全一样的脚本,我在脚本声明好Java变量,一切就正常了。。在N次重写systemd.unit和脚本中,无意中发现的。
另外,我试了不加nohup,会一直挂在启动过程

5555太难了。

然后我现在想尝试把两个启动和停止函数,写成一个while循环,或者使用case语句,虽然现在的脚本已经可以用了,但也是一种追求,哈哈

贴上正常的脚本:
https://paste.ubuntu.com/p/RwbKjBhq8X/

感谢大佬的帮助!
页: [1]
查看完整版本: systemd.unit无法执行具有while循环的脚本?