嵌入式 linux 应用程序启动脚本在命令行下效果更好

Embedded linux application start script works better from command line

我运行正在 Altera FPGA 上嵌入 linux。它使用 SystemD 运行 启动,我在 "multi-user.target.wants" 部分有一个脚本 运行 我的应用程序。

当它 运行 启动时我的代码 运行 比我 运行 来自 ssh shell 的相同脚本时慢 运行s shell。

我已经检查过路径是否相同,脚本的权限是否正确,脚本中是否使用了完整路径。使用 'top' 我可以看到为不同线程启动的优先级设置相同,但不知何故两种启动方式之间的性能完全不同。

完整的脚本是:

#!/bin/sh
sleep 5s
mount /dev/mmcblk0p5 /home/root/linux
cd /home/root/linux/mem_driver
./memdev_load
cd /home/root/linux/gpio_driver
insmod ./gpiodev.ko
mknod /dev/gpiodev c 249 0
sleep 5s
cd /home/root/src/control
mysqld_safe &
up=0
while [ $up -ne 2 ] 
do
    up=$(pgrep mysql | wc -l);
    echo $up
done
sleep 3s
cd /home/root/studio_web/myapp
npm start &
sleep 1s
cd /home/root/src/control
#sleep 1s
./control > /home/root/linux/output.log

已插入各种睡眠命令以尝试确保一切以正确的顺序启动。

如果您能帮助我们诊断其行为为何不同,我们将不胜感激。

这是您使用的唯一 shell 脚本吗?或者您是否有一个执行单个 shell 脚本的 systemd 服务文件?

这里使用sleep是无效的。您应该将它们分成单独的 shell 脚本,然后使用 systemd 确保 shell 脚本按顺序排列 运行。

例如,我们想先挂载目录,因为如果挂载失败,那么后面的都不会成功。所以我们创建一个systemd挂载服务:

# home-root-linux.mount
[Unit] 
Description=Mount /home/root/linux
Before=gpiodev.service

[Mount]
What=/dev/mmcblk0p5 
Where=/home/root/linux 
Options=defaults

[Install] 
WantedBy=multi-user.target

然后我们可以在执行之前用sleep分隔的shell脚本的三个部分之前创建另一个依赖于上面挂载的systemd服务,以确保它们是运行 按顺序。

# gpiodev.service
[Unit]
Description=Handle gpiodev kernel module
After=home-root-linux.mount
Before=mysqlsafe.service

[Service]
Type=oneshot
ExecStartPre=/home/root/linux/mem_driver/memdev_load
ExecStart=/sbin/insmod gpiodev.ko; /bin/mknod /dev/gpiodev c 249 0
WorkingDirectory=/home/root/linux/gpio_driver
RemainAfterExit=yes
StandardOutput=journal

[Install]
WantedBy=multi-user.target

systemd 服务的第二部分(在 sleep 之后)。在本例中,我们有一个单独的 shell 脚本,它位于 /sbin/ 中,因为它包含一个 while 循环,因此最好将其分开:

# mysqlsafe.service
[Unit]
Description=MySQL safe
After=gpiodev.service
Before=npmoutput.service

[Service]
Type=oneshot
ExecStart=/sbin/mysqlsafe.sh
WorkingDirectory=/home/root/src/control
RemainAfterExit=yes
StandardOutput=journal

[Install]
WantedBy=multi-user.target

在上面的systemd服务中执行的shell脚本的第二部分(由于复杂而分开到一个单独的文件中):

# /sbin/mysqlsafe.sh
#!/bin/sh
mysqld_safe &
up=0
while [ $up -ne 2 ] 
do
    up=$(pgrep mysql | wc -l);
    echo $up
done

systemd服务的第三部分(原shell脚本的第三部分被sleep分隔):

# mpmoutput.service
[Unit]
Description=npm and output to log
After=mysqlsafe.service

[Service]
Type=oneshot
ExecStartPre=/usr/bin/npm &
ExecStart=/home/root/src/control > /home/root/linux/output.log
WorkingDirectory=/home/root/studio_web/myapp
RemainAfterExit=yes
StandardOutput=journal

[Install]
WantedBy=multi-user.target

这种方法背后的想法是 systemd 认识到每个服务的重要性以及对后续服务的依赖,即如果一个服务失败,队列中的后续服务将不会执行。然后您可以使用 systemctl 进行检查并查看登录 journalctl.

只需快速复制、粘贴和编辑即可。可能包含错误,因为它未经测试或检查。

有关 systemd 服务文件的更多阅读可以在这里找到:https://www.freedesktop.org/software/systemd/man/systemd.service.html