You told me in other comment that your system shows this:
$ systemctl get-default
graphical.target
So, change it to multi-user.target:
$ sudo systemctl set-default multi-user.target
And multi-user.target will start at tty1 (Ctrl+Alt+F1):
$ systemctl list-dependencies multi-user.target | grep getty
● ├─getty.target
● │ ├─getty-static.service
● │ └─getty@tty1.service
So, we override tty1 file:
$ sudo systemctl edit getty@tty1
With this content (which m is your username):
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin m %I $TERM
/sbin/agetty above might different in your system, ensure your check the correct path with:
$ type -a agetty
agetty is /sbin/agetty
agetty is /sbin/agetty
Press Esc, then shift + z + z to save and quit (this keys is for vim, you can run ps a in other terminal tab while edit to know its command is editor /etc/systemd/system/getty@tty1.service.d/.#override.blahblah, in which editor is symlink to vim.gtk3 in my system, your system may vary).
$ type -a editor
editor is /usr/bin/editor
editor is /usr/bin/editor
$ realpath /usr/bin/editor
/usr/bin/vim.gtk3
Then cat the getty@tty1 and navigate to bottom, you will know it simply append this lines make override effect:
$ sudo systemctl cat getty@tty1
...
# /etc/systemd/system/getty@tty1.service.d/override.conf
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin xiaobai %I $TERM
Auto login done by --autologin above, otherwise you need manually type username and password to login in tty1 after boot.
After loggedin to tty1 with username m, it will execute /home/m/.profile, so add this line at the end of your /home/m/.profile:
echo "$DISPLAY" > /tmp/hole1
echo "$XDG_VTNR" > /tmp/hole2
if [ -z "$DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; then
echo lolo > /tmp/hole3
exec startx -- -nocursor
fi
echo lili > /tmp/hole4
/tmp/holeN above is for debug purpose only, in order to know it run as desired. e.g. If /tmp/hole3 not created but /tmp/hole2 was created, that's means you need to cat /tmp/hole2 to check the value of "$XDG_VTNR" .
startx will then execute /home/m/.xinitrc, edit it:
$ cat /home/m/.xinitrc
#!/usr/bin/env bash
echo 55 > /tmp/test1
exec openbox-session
echo 55 > /tmp/test2
openbox-session will then execute /home/m/.config/openbox/autostart, edit it as usual:
$ cat /home/m/.config/openbox/autostart
echo 7 > /tmp/yy
/home/m/img &
echo 8 > /tmp/yy2
After all, reboot, will take you to shows your image directly, the instruction above can be summarized as:
multi-user.target -> tty1 -> run getty@tty1.service -> ExecStart
auto login with desired username -> logged-in will execute ~/.profile -> exec startx ->
startx will execute ~/.xinitrc -> exec openbox-session -> openbox
will execute ~/.config/openbox/autostart -> /home/m/img & will pop
up.
[UPDATE]
I chat with OP in chat room (transcript) and solved his problem.
rc.local able to startx because of rc.local run startx as root, but ~/.profile is not run startx as root. We do startx > /tmp/my.log 2>&1 to ensure startx run correctly, then /tmp/my.log will shows we need to check /home/m/.local/share/xorg/Xorg.0.log, and eventually I noticed the first (EE) is (EE) open /dev/fb8: Permission denied.
OP need to add user m to video group to obtain permission when startx to access desired FRAMEBUFFER /dev/fb8.
sudo usermod -a -G audio m
sudo usermod -a -G video m
ref1, ref2
p/s: I wonder add to audio group above is necessary. ref