基于Yocto系统:开机无法同时启动C++程序与Node.js Web服务器
问题分析与解决方案
你遇到的核心问题很明确:你的init.d脚本是同步执行的,第一个C++程序在前台运行,会阻塞脚本继续执行后面的Node.js启动命令——脚本会一直停在/home/ProjectFolder/myProject这一行,直到这个进程退出才会往下走,而开机后这个C++程序一直在运行,所以Node.js永远没机会启动。
下面给你两种解决思路,从快速修复到长期更可靠的方案:
快速修复:让进程后台运行
修改你的init.d脚本,给每个启动命令加上&符号,让进程在后台运行,这样脚本不会被阻塞,能继续执行下一条命令:
#! /bin/bash # 让C++程序后台运行,同时重定向日志到文件(方便排查问题) /home/ProjectFolder/myProject >> /var/log/myProject.log 2>&1 & # 同样处理Node.js服务 cd /home/myapp && DEBUG=myapp:* npm start >> /var/log/myapp.log 2>&1 & exit 0
&:将进程放到后台执行,脚本立即继续执行下一行>> /var/log/xxx.log:把程序的标准输出追加到日志文件2>&1:把错误输出(stderr)重定向到和标准输出(stdout)同一个文件,避免错误信息丢失
修改后重新设置开机启动(如果之前已经设置过,可直接覆盖脚本后刷新权限):
chmod +x /etc/init.d/startProg.sh update-rc.d startProg.sh defaults
长期更优方案:用Systemd服务(Yocto推荐)
现在大多数Yocto构建的系统默认使用Systemd代替传统的SysVinit(init.d),Systemd能更好地管理进程生命周期(比如进程崩溃自动重启、依赖顺序控制),更适合嵌入式系统场景。
步骤1:创建Systemd服务文件
给你的C++程序和Node.js服务分别创建独立的.service文件:
1. C++程序服务文件 /etc/systemd/system/myProject.service
[Unit] Description=My C++ Application # 如果程序不需要网络,可以去掉After=network.target After=network.target [Service] # 程序的绝对路径 ExecStart=/home/ProjectFolder/myProject # 进程崩溃时自动重启 Restart=always # 以root用户运行(如果不需要root,可以改成其他用户) User=root # 重定向日志到systemd日志系统(可以用journalctl查看) StandardOutput=journal+console StandardError=journal+console [Install] # 设置为多用户目标下的开机启动项 WantedBy=multi-user.target
2. Node.js服务文件 /etc/systemd/system/myapp.service
[Unit] Description=My Node.js Web Server # 如果Node.js需要依赖C++程序先启动,加上After=myProject.service After=network.target myProject.service [Service] # 设置工作目录 WorkingDirectory=/home/myapp # 设置环境变量 Environment=DEBUG=myapp:* # npm的绝对路径(如果不知道可以用`which npm`查看) ExecStart=/usr/bin/npm start # 进程崩溃自动重启 Restart=always User=root StandardOutput=journal+console StandardError=journal+console [Install] WantedBy=multi-user.target
步骤2:启用并启动服务
# 重新加载systemd配置 systemctl daemon-reload # 设置开机自启 systemctl enable myProject.service myapp.service # 立即启动服务(不需要重启) systemctl start myProject.service myapp.service
查看日志与状态
用以下命令查看服务状态和日志:
# 查看服务运行状态 systemctl status myProject.service myapp.service # 实时查看程序日志 journalctl -u myProject.service -f journalctl -u myapp.service -f
清理旧的init.d脚本
如果改用Systemd,记得禁用之前的init.d脚本,避免冲突:
update-rc.d -f startProg.sh remove
内容的提问来源于stack exchange,提问作者Tim Wollentin
相关产品推荐
相关产品推荐

