I have a C program running to do some stuff when i push a button on my raspberry pi. 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.

The script is running from rc.local and other functions from the script work. Only this part does not.

System("xdotool key ctrl+Tab");

It is supposed to cycle trough a range of opened tabs in chromium webbrowser.

  • Not to nitpick, but (I've edited this out) "script" refers to source code which is run through an interpreter -- e.g., a bash script, a python script, etc. Sometimes this is done in two stages (compilation to byte code -> execution by bytecode interpreter), but it is fundamentally different from how C source is used. C is pre-compiled to machine code by a C compiler, and the resulting binary executable does not use an interpreter -- hence it is an executable program and not any form of "script". C source itself is never refer to as "script" either, it's just code.
    – goldilocks
    Commented Jun 7, 2016 at 7:11

1 Answer 1


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.

  • Thanks! I added the execution of the program to autostart and everything is working fine! Thanks again for the detail explanation, i now know why this works.
    – ApieVuist
    Commented Jun 7, 2016 at 21:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.