Shutdown your machine automatically (or from remote)
July 11, 2009
I was wondering whether it is possible to shutdown a KDE 4 session programmatically. The obvious solution is “sudo shutdown -h now”, but this requires me to enter my root password. The manpage shutdown(8) mentions a file /etc/shutdown.allow which could define users allowed to shutdown the machine, but this does not seem to work. (I put myself into that file, and shutdown keeps telling me that I must be root to do that.)
That was too much of a hassle for me, so I looked for a KDE-ish solution to the problem. And whenever you need to access KDE functionality from the command line, DBus is your friend. I quickly found on the session bus the org.kde.ksmserver service, which contains no shutdown() method, but a logout() method. Technically, both things are fairly similar, so let’s look into this method: Okay, it takes three int parameters. What would MacGyver do now?
I eventually found what these parameters are. Reading the code of KSMServer and the KWorkspace library, the three parameters are values from the enumerations KWorkspace::ShutdownConfirm, KWorkspace::ShutdownType, KWorkspace::ShutdownMode (in that particular order). The possible values for these enumerations can be found in the API documentation for KWorkspace. For example, to shutdown your machine from the command line, say:
$ qdbus org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout 0 2 2
The parameters mean that, without confirmation (the 0), the machine should be shut down (the first 2) immediately (the second 2). So if you ever wanted e.g. to shutdown your machine from remote, now you know how to do it. (Perhaps this could be put on one of our wikis, but I’m unsure which one of Techbase and Userbase is the right one, and where to put it there.)
Update 1: Milian Wolff correctly mentioned in the comments that KShutdown simplifies this task very much. I had also used KShutdown in KDE 3, but had forgotten about it because the port was not done when I switched to KDE 4 as my main desktop.
Update 2: A commenter asked for a more detailed guide on how to get to such information. As an example, I’ll show you how to find the command that toggles KWin’s compositing: (I know of Alt-Shift-F12, but one might want to do this in a script)
- Call qdbus without parameters to get a list of all registered services. Tthe numerical names such as “:1.42” can be ignored, as most programs register more readable names such as “org.kde.ksmserver. Some of thesed named services have some numerical suffix, this is the process ID for applications which can have multiple instances at once.
- When you’ve found the right service, give its name as the first parameter to qdbus. In this example, you would then invoke “qdbus org.kde.kwin”. qdbus will now print all interfaces in this service. All KDE applications have a “/MainApplication” interface to control the application in a generic name. (This generic interface is used by kquitapp, for instance.)
- Pass the name of the right interface (“/KWin” in our case) as the second parameter to qdbus. Now, you’ll see an extensive list of all methods and signals that this interface provides. While signals allow the service to pass information to its clients, methods allow to invoke certain things in the service. In our case, the right method is:
method Q_NOREPLY void org.kde.KWin.toggleCompositing()
- Add the name of the method, which is “org.kde.KWin.toggleCompositing” in the above example, as the third and last parameter to your final qdbus call. If the method in question has arguments (like the above “org.kde.KSMServerInterface.logout” method), give these in the right order as further arguments. (Of course, you have to know what these parameters mean, which was not that apparent in the KSMServer case.)