11

For example, I normally open mousepad (xfce equivalent of gedit) from the applications menu. However, I know that you can also do this in a terminal by typing mousepad.

Following this example, what I want is whenever I open mousepad via GUI, a new line is written in a log file stating something like Sep 5 15:35:11 lucho@lucho:~$ mousepad. More in general, what I want is to log all GUI activities that are potentially do-able via command-line (like opening programs, changing permissions, modifying a system settings, etc) but written in its alternative command-line execution format. I want this in order to improve my knowledge of how to use the command-line (without going through the man pages). There are many things I do through the GUI which I don't do via command-line (some potentially automatable via a script or via keyboard shortcuts) and having this log file would be a good way to learn them.

I'm aware of the existence of the syslog file in /var/log but that is not what I need. The Activity Log Manager app from Ubuntu repositories does not show command-line format, so far as I know. I need something like the .bash_history file that exist in my home folder but recording my GUI-based activities.

5
  • you can use a tool like strace to peek into a running program and see what system calls it makes , this will generate vast amounts of data though
    – Amias
    Jan 23, 2017 at 12:43
  • If you're looking for a program that simply logs the binary name of programs that open in GUI, I can do that in a script. If it's what you want, let me know. Would be better if you clarified what your requirements actually are, so please edit your question. Recording GUI-based activities , such as clicking on buttons or opening new tab in a browser isn't something that can be easily recorded, because these aren't connected to actual shell commands Jan 24, 2017 at 21:16
  • @Serg The log you suggest would be certainly what I am looking for. Something like a "Task Manager" log based on CLI names instead of GLI names, which, as the existing answer suggest, might not coincide. For instance, if I open "Language Support" in Settings, I want to know its CLI equivalent. Etc...
    – user308164
    Jan 25, 2017 at 9:57
  • @luchonacho OK, I will begin writing today, will post when it's ready. By the way, "Language Support" in Settings doesn't have cli equivalent of its own. Some of the things, like bluetooth menu or background menu, do - you can specify unity-control-center background or gnome-control-center background (depending on your desktop, Unity or XFCE or GNOME). But the outside world probably only will see gnome-control-center Jan 25, 2017 at 14:48
  • There are many, many ways to find out what task is done by GUI applications, and find out what their cli equivalent is. It seems quite inefficient to me to try to blindly record everything that happens by brute force, being sure that you won't catch all. Better find out in specific cases, using specific tools. Jan 28, 2017 at 14:05

2 Answers 2

4

Proposing that kind log file as base for learning is actually a brilliant idea!

Unfourtunately, many actions of GUI programs are implemented in the program itself, not using external commands; And even if it uses external commands, it may be in a different way than one would do it in a shell;
So that does not exist, and is not easy to implement.

But I have a solution for a part of the problem: The program name in the GUI is sometimes differen from the program name one needs to know for a shell command - not only if the GUI name is translated to a local language.

For example, how to start the program Files in the comman line?

We need to look into all *.desktop files for the name. There, we find the command in the Exec line:

locate -b '.desktop' | xargs grep -ls '^Name.*=Files$' | xargs grep '^Exec.*'

lists desktop file names and commands for the GUI program File - replace that with the exact name you look for - even it it's multiple words (for substring search, leave out the = and $).

With the command, I find Files may be nautilus, dolphin or active-filebrowser:

/etc/xdg/autostart/nautilus-autostart.desktop:Exec=nautilus -n
/usr/share/app-install/desktop/nemo:nemo.desktop:Exec=nemo %U
/usr/share/app-install/desktop/plasma-active:kde4__active-filebrowser.desktop:Exec=active-filebrowser -graphicssystem raster %u
/usr/share/applications/nautilus-folder-handler.desktop:Exec=nautilus %U
/usr/share/applications/nautilus.desktop:Exec=nautilus --new-window %U
/usr/share/applications/nautilus.desktop:Exec=nautilus --new-window
2
  • Mmm, my question underlies a view of linux of a scaled complexity, where more elaborated programs are build upon simpler code, so I thought any GUI application is relying on terminal commands but might not be the case since terminal is based on bash code whereas software could be written in python or c++ or etc. Am I wrong?
    – user308164
    Sep 7, 2014 at 21:32
  • The layers of complexity do exist, but in a different way: rougnly, there are system calls, library functions, and on top either a graphical user interface, or a command line interface - they are alternatives. Sep 8, 2014 at 11:44
2
+250

Introduction

While it's not possible to log all GUI actions, such things as logging commands that correspond to open windows can be done. Below is the simple python script that does the job. It's still in development, but does 90% of the required task.

Source code

#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk,Gtk
import time
import os
import subprocess

def run_cmd(cmdlist):
    """ Reusable function for running external commands """
    new_env = dict(os.environ)
    new_env['LC_ALL'] = 'C'
    try:
        stdout = subprocess.check_output(cmdlist, env=new_env)
    except subprocess.CalledProcessError:
        pass
    else:
        if stdout:
            return stdout
def print_info(stack,event):
    base_xprop = ['xprop','-notype']
    for xid in stack:
        pid = None
        check_pid = run_cmd(base_xprop + [ '_NET_WM_PID', '-id',str(xid)])
        if check_pid:
            pid = check_pid.decode().split('=')[1].strip()
        with open('/proc/'+pid+'/cmdline') as fd:
            command = fd.read()
        print(time.strftime("%D %H:%M:%S" + " "*3) + event + pid + " " + command)

def main():
    sc = Gdk.Screen.get_default()
    old_stack = None

    while True:
        stack = [ win.get_xid() for win in sc.get_window_stack() ]
        if old_stack:
            # Difference between current and old stack will show new programs
            diff = set(stack) - set(old_stack)
            if diff:
                print_info(diff," 'New window open' ")
        else:
            print_info(stack," 'Script Started' ")

        old_stack = stack
        time.sleep(2)

if __name__ == '__main__': main()

Test run:

$ ./log_open_windows.py                                                                                                
01/25/17 15:33:13    'Script Started' 2915 nautilus-n
01/25/17 15:33:13    'Script Started' 3408 /opt/google/chrome/chrome
01/25/17 15:33:13    'Script Started' 12540 /usr/bin/python/usr/bin/x-terminal-emulator
01/25/17 15:33:13    'Script Started' 2454 compiz
01/25/17 15:33:13    'Script Started' 2454 compiz
01/25/17 15:33:13    'Script Started' 2454 compiz
01/25/17 15:33:13    'Script Started' 2454 compiz
01/25/17 15:33:13    'Script Started' 2454 compiz
01/25/17 15:33:21    'New window open' 15143 /usr/lib/firefox/firefox-new-window
01/25/17 15:33:27    'New window open' 15196 unity-control-center

The script shows timestamp, event type, the window PID, and the corresponding command.

How to use

The standard rules of any script apply. Make sure you store the script in ~/bin directory. If you don't have ~/bin directory , then create one. Save script file there and ensure it is executable with chmod +x ~/bin/log_open_windows.py. After than you can run it from command line at any time you wish by calling ~/log_open_windows.py in command-line.

4
  • Thanks. Looks promising! Two questions. How to run it? What's the 10% missing?
    – user308164
    Jan 26, 2017 at 9:52
  • Nifty! +1 from me!
    – Fabby
    Jan 26, 2017 at 13:22
  • @luchonacho I added a paragraph on usage. I would recommend you use it manually from command-line as I described. You can make it start automatically on start-up, but I don't recommend doing that. The missing 10% is other few features I wanted to add, but I don't think I'm going to add them. It works well enough for now. But maybe I'll change my mind again Jan 28, 2017 at 16:47
  • This is probably the closest you can get to what I was looking for, knowingly that the perfect solution does not exist. Thanks!
    – user308164
    Jan 28, 2017 at 18:34

You must log in to answer this question.