When i run this program from a shell window, everthing works fine. However when i run the exact same program from rc.local this specific function does not work.
System("xdotool key ctrl+Tab");
There's some confusion amongst Raspbian users about the difference between boot and login due to the common practice of using autologin with the GUI, amalgamating two distinct sequences.
Boot refers to the loading of the OS kernel, which then executes a "first program" known generally as init (more specifically, on current versions of Raspbian this program is systemd
). The init program then manages the rest of the boot process, which involves starting a number of other programs -- only one is ever started by the kernel, init, and since all programs must then be started by another program, it follows that everything running on the system can be traced back to init, which always has a PID of 1 even when restarted, and cannot be effectively stopped.
One of the programs typically started late in this process is a graphical "display manager" which is the GUI equivalent of a login prompt on systems which don't use a GUI by default. This is where someone has the opportunity to log in and interact with the system as a specific user.
Login refers to a sequence of things done when a user logs in. This "sequence" may be very simple, e.g., starting an interactive command shell (on Raspbian, bash
; this is the same program used inside GUI terminals), which includes running its own little set of start-up scripts.
If the login is via a GUI display manager, presumably a full-blown desktop is then instantiated which involves a larger set of other programs necessary to its functioning. This environment also includes start-up scripts run by a non-interactive shell, or the desktop core itself.
Since autologin sort of conflates these two sequences, it can seem that they are really one and the same, and this is where you have gotten snagged.
Processes executed by init as part of the boot sequence, including the /etc/rc.local
shell script, are run as particular users (every process is), most often root
(as is the case with /etc/rc.local
), but this does not require those users be logged in (in fact, it is impossible to log some of them in). This is significant because logins are "sessions" where all the processes that are part of the session are descended from the login itself, which is descended from init. That does not include /etc/rc.local
, which is run directly by init and is not part of any login session.
The post login GUI desktop is part of your login session as a particular user, e.g., pi
. While the root
user does have the power to poke into this, for the most part it isn't involved. The Xorg server (or just "X server", or sometimes "X11 server"), which is the foundation of the higher level aspects of the GUI desktop, is part of a login session and as such runs as the user of that session.
The point here is that /etc/rc.local
actually isn't part of your login session, while your GUI desktop and programs within it such as a web browser are. If you try and debug your problem using the methodology suggested here, you will probably find the issue is that xdotool
, which depends on an X server to function, isn't associated with one when run this way ("No display found").
The solution is to instead execute the program as part of your GUI login, not from a boot script. Exactly how to do this depends on the upper layers of software stack you are using with the GUI; on Raspbian this is LXDE. For running things post login in a manner similar to the way /etc/rc.local
is used to execute things near the end of the boot sequence, LXDE deploys both "system wide" (i.e., applied to all users, but on a case by case basis) and "per user" (i.e., customized for one particular user) facilities. The two configuration files for this are, respectively, /etc/xdg/lxsession/LXDE-pi/autostart
and $HOME/.config/lxsession/LXDE-pi/autostart
. You probably want the latter.
Note these aren't shell scripts so exactly how you use them is not the same as rc.local
. I don't use LXDE personally, so I can't go into detail about that, but if you look at the last linked question and search here and online generally for LXDE autostart
you will find many examples -- I do not think it is very complicated.
That's not a guarantee that what you are trying to do will work, but it is a much better starting place, and if someone comes along with a briefer, more pragmatic demonstration, you have this technical explanation to go along with it.