Linux配置应用自启动,碰到一些问题

最近在搞一个arm-linux,发现自动运行与手动运行,竟然效果是不一样,在解决问题的同时,也顺便把Linux启动相关一些知识梳理一遍。

  • 问题1:在/etc/init.d/ 新建一个S90startapp, 并且添加启动程序的路径。

此时,会发现该程序启动失败,并提示如下信息:

qt.qpa.plugin: Could not find the Qt platform plugin "eglfs" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: linuxfb, minimal, offscreen, vnc, wayland-egl, wayland.

大概的意思:程序是Qt的,不能 在wayland下运行程序

如果将启动链接放在S50launcher 里面,是可以正常启动的。

那么问题来了,如果添加自定义启动配置,要怎么配置。

先来看看,可以使用的S90startapp 配置 :

#
# Start app launcher...
#

case "$1" in
  start)
                printf "Starting Application launcher: "         

                export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/var/run}
                export QT_QPA_PLATFORM=${QT_QPA_PLATFORM:-wayland}  #关键是这句话,要添加环境变量
                            
                /userdata/tmp/AppServer &
                
        ;;
  stop)
                killall AppServer               
                printf "stop finished"
        ;;
  *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac
exit 0

时间解决的关键是要添加:

export QT_QPA_PLATFORM=${QT_QPA_PLATFORM:-wayland}

当然如果偷懒,这个环境变量放在 /etc/profile 里也是可以(这样就是全局行为)

奇怪的是,明明在S50launcher里面以及设置过该环境变量,这里为什么还要设置?

这个就是要关于 export这个命令,如果是该shell下执行的export 也就是仅仅该shell下生效,当切换或重新打开shell,那么export之后的内容都是无效的。

Linux,一般来说都是通过rcS来加载Sxx的启动脚本。因此,分析下rcS:

#!/bin/sh


# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do

     # Ignore dangling symlinks (if any).
     [ ! -f "$i" ] && continue

     case "$i" in
        *.sh)
            # Source shell script for speed.
            (
                trap - INT QUIT TSTP
                set start
                . $i
            )
            ;;
        *)
            # No sh extension, so fork subprocess.
            $i start   #这里,也就是说每加载一个Sxx文件,会调用该脚本的start,每次都是fork subprocess方式加载(重新开启进程)
            ;;
    esac
done

知道原理,其实就好解决了,疑惑也解开了。

梳理:

  1. 系统启动后,执行/etc/init.d/rcS

  1. rcS 加载 /etc/init.d/S?? 开头脚本。每次都是fork方式加载

  1. 因此如果临时修改环境变量,那么仅对本脚本生效

  1. 可以将环境变量放在 /etc/profile

  • 问题2:自动其他程序的时候,会出现如下warning:

sh: warning: setlocale: LC_ALL: cannot change locale (zh_CN.utf8)

大概意思,在shell下不能切换本地语言为zh_CN.utf8

实测:这句话,仅仅是warning,对功能并不影响(也不影响qt界面显示中文);

网上也搜索一堆,但都是要装个语言包之类的,显然不是arm-linux下解决办法。

竟然是应用程序引起这个warning,所以花了点时间,找下哪个fun产生的。通过不懈努力,后来发现

每当执行一边:popen,就会触发以上warn信息

FILE *pp = popen(cmd, "r");

翻阅了网上一些资料,发现popen是启动 sh -c 执行对应CMD的,也就是fork 出子进程方式进行,由于此时fork跟父进程一致,才导致该warning出现

解决办法:反正cmd也不会用到中文的,

索性就用:LC_ALL=C 就可以了。也就是说在S50launcher 里export LC_ALL=C就可以

扩展S50launcher知识:

#
# Start linux launcher...
#

# Load default env variables from profiles(e.g. /etc/profile.d/weston.sh)
. /etc/profile    #将profile里设置

case "$1" in
  start)
                printf "Starting launcher: "
                export LC_ALL=C    #设置语言,也就是本shell生效
                #export LC_ALL='zh_CN.utf8'  #原先设置

                # Uncomment to disable mirror mode
                # unset WESTON_DRM_MIRROR

                export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/var/run}
                export QT_QPA_PLATFORM=${QT_QPA_PLATFORM:-wayland}  #设置qt运行在wayland
                echo 3 > /sys/class/graphics/fb0/blank

                weston --tty=2 --idle-time=0&
                {
                        # Wait for weston ready
                        while [ ! -e ${XDG_RUNTIME_DIR}/wayland-0 ]; do
                                sleep .1   #等待wayland启动成功
                        done
                        #/usr/bin/QLauncher &     #原先桌面程序,可以屏蔽掉                    
                        #/userdata/tmp/AppServer &  #添加自己的启动程序
                        echo 0 > /sys/class/graphics/fb0/blank   
                }&
        ;;
  stop)
                killall AppServer   #当系统重启或退出的时候,调用stop
                killall weston
                printf "stop finished"
        ;;
  *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac
exit 0

梳理:

当系统启动时候,调用 /etc/init.d/rcS 然后调用各个Sxx 的脚本 "start)"

当系统推出时候,调用 /etc/init.d/rcK 然后调用各个Sxx脚本的 "stop)"

posted @ 2023-02-03 09:21  小刚学长  阅读(248)  评论(0编辑  收藏  举报