Skip to content

Commit

Permalink
Merge pull request #6 from FrostyX/develop
Browse files Browse the repository at this point in the history
Version 0.3
  • Loading branch information
FrostyX committed May 13, 2014
2 parents 59a9142 + f682c0f commit 8d660f2
Show file tree
Hide file tree
Showing 35 changed files with 1,388 additions and 106 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

Tracer finds outdated running packages in your system
Tracer finds outdated running applications in your system
Copyright (C) 2013 Jakub Kadlčík

This program is free software; you can redistribute it and/or modify
Expand Down
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# tracer

Tracer finds outdated running packages in your system
Tracer finds outdated running applications in your system

How does he do it? He simply finds all packages you have modified since you boot up. Then he traces their files in the jungle of your memory, ... senses them, and finally, finds them. In the end you will get list of packages what have been running while you updated or removed them.

## Requirements
- Supported linux distribution - There are currently supported [Fedora](http://fedoraproject.org/) and [Gentoo](http://www.gentoo.org/)
- Python interpreter
- Python [psutil](https://code.google.com/p/psutil/) module. Available [here](https://admin.fedoraproject.org/pkgdb/acls/name/python-psutil) and [here](https://packages.gentoo.org/package/dev-python/psutil). Please use testing version on gentoo.
- Python [beautifulsoup](http://www.crummy.com/software/BeautifulSoup/bs4/doc/) module. Available [here](https://admin.fedoraproject.org/pkgdb/acls/name/python-beautifulsoup4) and [here](https://packages.gentoo.org/package/dev-python/beautifulsoup)

## Usage
### Basics
Expand Down Expand Up @@ -59,10 +60,18 @@ Tracer is called after every successful transaction.
vim-enhanced.i686 2:7.4.179-1.fc20

Calling tracer
vim-X11
gvim

Done!

If you cant see tracer section in your output, make sure that you don't have `plugins=0` in your `/etc/dnf/dnf.conf`.


## Feedback
Please report any bugs or feature requests to [issues](https://github.com/FrostyX/tracer/issues) on this repository. Pull requests are also welcome. If you rather want a talk or something, you can find me on `#gentoo.cs` or `#fedora-cs` `@freenode` or you can [mail me](mailto:[email protected]).


## References
- <https://pythonhosted.org/psutil/>
- <https://code.google.com/p/psutil/wiki/Documentation>
- <https://docs.python.org/2/library/unittest.html>
150 changes: 141 additions & 9 deletions bin/tracer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Tracer finds outdated running packages in your system
# Copyright 2013 Jakub Kadlčík
#-*- coding: utf-8 -*-
# tracer.py
# Tracer finds outdated running applications in your system
#
# Copyright (C) 2013 Jakub Kadlčík
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#

# Enable importing modules from parent directory (tracer's root directory)
import os
Expand All @@ -10,9 +24,15 @@

import sys
import time
import datetime
from resources.lang import _
from resources.tracer import Tracer
from resources.args_parser import args
from resources.package import Package
from resources.exceptions import UnsupportedDistribution
from resources.applications import Applications
import resources.memory as Memory
import resources.system as System


def main(argv=sys.argv, stdin=[]):
Expand All @@ -26,12 +46,124 @@ def main(argv=sys.argv, stdin=[]):
for package in args.packages + stdin_packages:
packages.append(Package(package, time.time() if args.now else None))

tracer = Tracer()
tracer.specified_packages = packages
tracer.now = args.now
for package in set(tracer.trace_running()):
# More times a package is updated the more times it is contained in a package list.
print package.name
try:
tracer = Tracer()
tracer.specified_packages = packages
tracer.now = args.now

processes = tracer.trace_running()
if not processes: return
if args.interactive: _print_all_interactive(processes)
else: _print_all(processes)

except UnsupportedDistribution as ex:
print ex

def _print_all(processes):
without_static = _exclude_type(processes, Applications.TYPES["STATIC"])
without_session = _exclude_type(without_static, Applications.TYPES["SESSION"])
for process in without_session:
print process.name

static_count = len(processes)-len(without_static)
session_count = len(without_static)-len(without_session)
_print_note_for_hidden(session_count, static_count)

def _print_all_interactive(processes):
processes = list(processes) # Cause Set is not ordered
without_static = _exclude_type(processes, Applications.TYPES["STATIC"])
without_session = _exclude_type(without_static, Applications.TYPES["SESSION"])
static_count = len(processes)-len(without_static)
session_count = len(without_static)-len(without_session)
while True:
i = 1
l = len(str(len(without_session))) # Number of digits in processes length
for process in without_session:
n = "[{0}]".format(i).ljust(l + 2)
print "{} {}".format(n, process.name)
i += 1
_print_note_for_hidden(session_count, static_count)

print "\n" + _("prompt_help")
answer = raw_input("--> ")
try:
if answer == "q": return
elif int(answer) <= 0 or int(answer) > i: raise IndexError
print_helper(without_session[int(answer) - 1].name)

except (SyntaxError, IndexError, ValueError):
print _("wrong_app_number")

raw_input(_("press_enter"))

def _exclude_type(processes, app_type):
"""app_type -- see Applications.TYPES"""
without = []
for process in processes:
app = Applications.find(process.name)
if app["type"] != app_type:
without.append(process)
return without

def _print_note_for_hidden(session_count, static_count):
if not args.quiet and (session_count > 0 or static_count > 0):
print "\n" + _("note_unlisted_apps")
if session_count > 0:
print _("requiring_session").format(session_count)

if static_count > 0:
print _("requiring_reboot").format(static_count)

def print_helper(app_name):
try:
tracer = Tracer()
package = tracer.package_info(app_name)
process = Memory.process_by_name(app_name)
app = Applications.find(app_name)

now = datetime.datetime.fromtimestamp(time.time())
started = datetime.datetime.fromtimestamp(process.create_time)
started = now - started

started_str = ""
if started.days > 0:
started_str = str(started.days) + " days"
elif started.seconds >= 60 * 60:
started_str = str(started.seconds / (60 * 60)) + " hours"
elif started.seconds >= 60:
started_str = str(started.seconds / 60) + " minutes"
elif started.seconds >= 0:
started_str = str(started.seconds) + " seconds"

how_to_restart = _("not_known_restart")
if app["type"] == Applications.TYPES["DAEMON"]:
init = System.init_system()
if init == "systemd": how_to_restart = "systemctl restart {0}".format(app["name"])
elif init == "init": how_to_restart = "/etc/init.d/{0} restart".format(app["name"])

print _("helper").format(
app_name = app_name,
pkg_name = package.name,
type = app["type"].capitalize(),
pkg_description = package.description,
user = process.username,
time = started_str,
pid = process.pid,
how_to_restart = how_to_restart,
)

except AttributeError:
print _("app_not_running").format(app_name)



if __name__ == '__main__':
if args.helper:
print_helper(args.helper[0])
sys.exit()

if os.getuid() != 0:
print _("root_only")
sys.exit();

main()
5 changes: 5 additions & 0 deletions data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## rules.xml
Rules in `rules.xml` are intended to find a proper processes. Rules defines path in processes tree from that one, which was affected by update through parents to the process, what user knows and what actually should be restarted.

## applications.xml
Definitions in `applications.xml` have nothing to do with searching. They are used just before application is printed to the output. They can set one of several types to the application (they can be printed differently) or define specific way, how to restart the application.
102 changes: 102 additions & 0 deletions data/applications.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!--
- applications.xml
- Defines the characteristics for specific applications
-
- Just before the application is printed, tracer looks into this file.
- When some definition matches, tracer examines its type. Daemons can be
- printed different way than regular applications. Also applications marked
- as 'static' will not be printed, cause only way how to restart them is reboot.
-
-
- Copyright (C) 2014 Jakub Kadlčík
-
- This copyrighted material is made available to anyone wishing to use,
- modify, copy, or redistribute it subject to the terms and conditions of
- the GNU General Public License v.2, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY expressed or implied, including the implied warranties of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- Public License for more details. You should have received a copy of the
- GNU General Public License along with this program; if not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-
-
- Available types:
- * daemon - Application is managed by init system
- * static - Application is restartable only through rebooting the system
- * session - Application is restartable only through restarting the session
- (i.e. Log out & Log in again)
-
- Application syntax:
- <app name="app_name1" type="daemon" />
- <app name="app_name2" helper="Run this command: app_name2 stop" />
- <app name="app_name3" rename="app_name_3" />
-
-
- Note that applications can be wrapped into group. In this case please set
- attributes to the group and omit them from applications
-
- Group syntax
- <group type="static">
- <app name="app_name1" />
- <app name="app_name2" />
- <app name="app_name3" />
- </group>
-
-->

<applications>

<!--
- Common applications
-->

<group type="daemon">
<app name="apache2" />
<app name="mpd" />
<app name="mysql" />
<app name="openvpn" />
<app name="samba" />
<app name="sshd" />
<app name="vixie-cron" />
<app name="wicd" />
</group>

<group type="static">
<app name="polkitd" />
<app name="udisksd" />
<app name="gvfsd" />
<app name="gvfs-afc-volume-monitor" />
<app name="gvfsd-metadata" />
<app name="gvfs-udisks2-volume-monitor" />
<app name="at-spi-bus-launcher" />
<app name="gconfd-2" />
<app name="upowerd" />
</group>

<group type="session">
<app name="dbus-launch" />
<app name="X" />
</group>


<!--
- KDE applications
-->

<group helper="Run `kdeinit4` command">
<app name="kdeinit4" />
<app name="klauncher" />
</group>

<group type="session">
<app name="kuiserver" />
<app name="kglobalaccel" />
<app name="kactivitymanagerd" />
<app name="kded4" />
<app name="knotify4" />
</group>

</applications>
59 changes: 59 additions & 0 deletions data/rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!--
- rules.xml
- Rules definitions for traced applications
-
- When process is found, tracer looks into this file and searches for its parent rules.
- If rule is found, action is performed. These two actions can be done:
- * Print the actual process
- * Find the rule for parent process
-
-
- Copyright (C) 2014 Jakub Kadlčík
-
- This copyrighted material is made available to anyone wishing to use,
- modify, copy, or redistribute it subject to the terms and conditions of
- the GNU General Public License v.2, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY expressed or implied, including the implied warranties of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- Public License for more details. You should have received a copy of the
- GNU General Public License along with this program; if not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-
-
- Rule syntax:
- <rule name="app_name" action="some_action" />
-
- Default action:
- 'call-parent'
-
- Available actions:
- 'call-parent', 'print'
-
-->

<rules>

<!-- KDE -->
<rule name="akonadiserver" />

<!-- Networking -->
<rule name="wicd" />

<!-- Web browsers -->
<rule name="chrome" />
<rule name="chrome-sandbox" />

</rules>

<!--
- @TODO - Deal with these applications:
- + Manages desktop:
- * Thunar
- * Nautilus
-
- + Test and add:
-
-->
3 changes: 2 additions & 1 deletion integration/dnf/plugins/tracer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#-*- coding: utf-8 -*-
# tracer.py, calls tracer after every successful transaction.
# tracer.py
# Calls tracer after every successful transaction.
# Also supplies the 'tracer' command.
#
# Copyright (C) 2014 Jakub Kadlčík
Expand Down
1 change: 1 addition & 0 deletions lang/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading

0 comments on commit 8d660f2

Please sign in to comment.