Kann ich in einer Protokolldatei alle GUI-basierten Aufgaben in ihrem alternativen Befehlszeilenformat anzeigen?

9

Zum Beispiel öffne ich normalerweise das Mauspad (xfce-Äquivalent von gedit) über das Anwendungsmenü. Ich weiß jedoch, dass Sie dies auch in einem Terminal durch Eingabe tun können mousepad.

Nach diesem Beispiel möchte ich immer dann, wenn ich das Mauspad über die GUI öffne, eine neue Zeile in eine Protokolldatei schreiben, in der so etwas wie angegeben ist Sep 5 15:35:11 lucho@lucho:~$ mousepad. Im Allgemeinen möchte ich alle GUI-Aktivitäten protokollieren, die möglicherweise über die Befehlszeile ausgeführt werden können (z. B. Öffnen von Programmen, Ändern von Berechtigungen, Ändern von Systemeinstellungen usw.), jedoch in ihrem alternativen Befehlszeilenausführungsformat geschrieben sind . Ich möchte dies, um meine Kenntnisse über die Verwendung der Befehlszeile zu verbessern (ohne die manSeiten durchzugehen). Es gibt viele Dinge, die ich über die GUI mache, die ich nicht über die Befehlszeile mache (einige können möglicherweise über ein Skript oder über Tastaturkürzel automatisiert werden), und diese Protokolldatei wäre eine gute Möglichkeit, sie zu lernen.

Ich bin mir der Existenz der Syslog-Datei in bewusst, /var/logaber das ist nicht das, was ich brauche. Die Activity Log Manager-App aus Ubuntu-Repositorys zeigt meines Wissens kein Befehlszeilenformat an. Ich benötige so etwas wie die .bash_history-Datei, die in meinem Home-Ordner vorhanden ist, aber meine GUI-basierten Aktivitäten aufzeichnet.


quelle
Sie können ein Tool wie strace verwenden, um einen Blick in ein laufendes Programm zu werfen und zu sehen, welche Systemaufrufe es macht.
Amias
Wenn Sie nach einem Programm suchen, das einfach den Binärnamen von Programmen protokolliert, die in der GUI geöffnet werden, kann ich dies in einem Skript tun. Wenn es das ist, was Sie wollen, lassen Sie es mich wissen. Wäre besser, wenn Sie klarstellen würden, was Ihre Anforderungen tatsächlich sind, also bearbeiten Sie bitte Ihre Frage. Das Aufzeichnen von GUI-basierten Aktivitäten wie das Klicken auf Schaltflächen oder das Öffnen eines neuen Tabs in einem Browser kann nicht einfach aufgezeichnet werden, da diese nicht mit tatsächlichen Shell-Befehlen verbunden sind
Sergiy Kolodyazhnyy
@Serg Das von Ihnen vorgeschlagene Protokoll ist mit Sicherheit das, wonach ich suche. So etwas wie ein "Task-Manager" -Protokoll, das auf CLI-Namen anstelle von GLI-Namen basiert und, wie die vorhandene Antwort andeutet, möglicherweise nicht übereinstimmt. Wenn ich beispielsweise "Sprachunterstützung" in den Einstellungen öffne, möchte ich die CLI-Entsprechung erfahren. Usw. ...
@luchonacho OK, ich werde heute anfangen zu schreiben, werde posten, wenn es fertig ist. Übrigens hat "Sprachunterstützung" in den Einstellungen kein eigenes CLI-Äquivalent. Einige der Dinge, wie das Bluetooth-Menü oder das Hintergrundmenü, können Sie angeben unity-control-center backgroundoder gnome-control-center background(abhängig von Ihrem Desktop, Unity oder XFCE oder GNOME). Aber die Außenwelt wird wahrscheinlich nur sehengnome-control-center
Sergiy Kolodyazhnyy
Es gibt viele, viele Möglichkeiten, um herauszufinden, welche Aufgabe GUI-Anwendungen ausführen, und um herauszufinden, welche CLI-Entsprechung sie haben. Es scheint mir ziemlich ineffizient zu sein, blind zu versuchen, alles aufzuzeichnen, was mit brutaler Gewalt geschieht, und dabei sicher zu sein, dass Sie nicht alle fangen. Finden Sie es in bestimmten Fällen besser heraus, indem Sie bestimmte Tools verwenden.
Jacob Vlijm

Antworten:

2

Einführung

Es ist zwar nicht möglich, alle GUI-Aktionen zu protokollieren , es können jedoch beispielsweise Protokollierungsbefehle ausgeführt werden, die geöffneten Fenstern entsprechen. Unten finden Sie das einfache Python-Skript, das die Aufgabe erledigt. Es befindet sich noch in der Entwicklung, erledigt aber 90% der erforderlichen Aufgabe.

Quellcode

#!/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()

Testlauf:

$ ./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

Das Skript zeigt den Zeitstempel, den Ereignistyp, die Fenster-PID und den entsprechenden Befehl an.

Wie benutzt man

Es gelten die Standardregeln eines Skripts. Stellen Sie sicher, dass Sie das Skript im ~/binVerzeichnis speichern . Wenn Sie kein ~/binVerzeichnis haben, erstellen Sie eines. Speichern Sie dort die Skriptdatei und stellen Sie sicher, dass sie mit ausführbar ist chmod +x ~/bin/log_open_windows.py. Danach können Sie es jederzeit über die Befehlszeile ausführen, indem Sie die ~/log_open_windows.pyBefehlszeile aufrufen .

Sergiy Kolodyazhnyy
quelle
Vielen Dank. Sieht vielversprechend aus! Zwei Fragen. Wie läuft es? Was fehlen den 10%?
Raffiniert! +1 von mir!
Fabby
@luchonacho Ich habe einen Absatz über die Verwendung hinzugefügt. Ich würde empfehlen, dass Sie es manuell über die Befehlszeile verwenden, wie ich beschrieben habe. Sie können es beim Start automatisch starten lassen, aber ich empfehle dies nicht. Die fehlenden 10% sind andere wenige Funktionen, die ich hinzufügen wollte, aber ich glaube nicht, dass ich sie hinzufügen werde. Es funktioniert vorerst gut genug. Aber vielleicht werde ich meine Meinung wieder ändern
Sergiy Kolodyazhnyy
Dies ist wahrscheinlich der nächste Punkt, den Sie erreichen können, da Sie wissen, dass es keine perfekte Lösung gibt. Vielen Dank!
4

Es ist eine brillante Idee, diese Art von Protokolldatei als Grundlage für das Lernen vorzuschlagen!

Leider werden viele Aktionen von GUI-Programmen im Programm selbst implementiert, ohne externe Befehle zu verwenden. Und selbst wenn externe Befehle verwendet werden, kann dies anders sein als in einer Shell.
Das gibt es also nicht und es ist nicht einfach zu implementieren.

Aber ich habe eine Lösung für einen Teil des Problems: Der Programmname in der GUI unterscheidet sich manchmal von dem Programmnamen, den man für einen Shell-Befehl kennen muss - nicht nur, wenn der GUI-Name in eine lokale Sprache übersetzt wird.

Wie Filesstarte ich beispielsweise das Programm in der Kommazeile?

Wir müssen in allen *.desktopDateien nach dem Namen suchen . Dort finden wir den Befehl in der ExecZeile:

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

listet Desktop-Dateinamen und Befehle für das GUI-Programm auf File- ersetzen Sie diesen durch den genauen Namen, nach dem Sie suchen - auch wenn es sich um mehrere Wörter handelt (lassen Sie für die Teilstringsuche das =und weg $).

Mit dem Befehl kann ich Filessein nautilus, dolphinoder 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
Volker Siegel
quelle
Mmm, meine Frage liegt einer Ansicht von Linux mit skalierter Komplexität zugrunde, bei der ausgefeiltere Programme auf einfacherem Code basieren. Daher dachte ich, dass jede GUI-Anwendung auf Terminalbefehlen basiert, dies jedoch möglicherweise nicht der Fall ist, da das Terminal auf Bash-Code basiert, während Software könnte in Python oder C ++ oder etc. geschrieben sein. Bin ich falsch?
Die Komplexitätsebenen existieren zwar, aber auf andere Weise: Grob gesagt gibt es Systemaufrufe, Bibliotheksfunktionen und darüber hinaus entweder eine grafische Benutzeroberfläche oder eine Befehlszeilenschnittstelle - sie sind Alternativen.
Volker Siegel