def print_helper(self, app_name, args): processes = Applications.find(app_name).instances if processes: manager = System.package_manager() package = manager.provided_by(app_name) if package: package.load_info(System.package_manager()) tr = Tracer(System.package_manager(), Rules, Applications) tr.now = self.args.now if self.packages: tr.specified_packages = self.packages try: affected_by = tr.trace_application(app_name) except AccessDenied: affected_by = _("You don't have enough permissions") app = Applications.find(app_name) affects = self._affects(app, affected_by) view = HelperView() view.assign("args", args) view.assign("processes", processes) view.assign("application", app) view.assign("package", package) view.assign("affected_by", affected_by) view.assign("affects", affects) view.render() else: print(_("Application called {0} is not running").format(app_name))
def _print_all_interactive(processes, args): filtered = processes.exclude_types([ Applications.TYPES['STATIC'], Applications.TYPES['SESSION'] ]) if not args.all else processes while True: i = 1 digits = len(str(len(filtered))) for process in filtered: n = "[{0}]".format(i).ljust(digits + 2) print "{} {}".format(n, process.name) i += 1 if not args.all: _print_note_for_hidden( len(processes), processes.count_type(Applications.TYPES['SESSION']), processes.count_type(Applications.TYPES['STATIC']) ) print "\n" + _("prompt_help") answer = raw_input("--> ") try: if answer == "q": return elif int(answer) <= 0 or int(answer) > i: raise IndexError print_helper(filtered[int(answer) - 1].name) except (SyntaxError, IndexError, ValueError): print _("wrong_app_number") raw_input(_("press_enter"))
def print_helper(self, app, args): if app.instances: manager = System.package_manager() package = manager.provided_by(app) if package: package.load_info(System.package_manager()) tr = Tracer(System.package_manager(), Rules, Applications) tr.now = self.args.now if self.packages: tr.specified_packages = self.packages try: affected_by = tr.trace_application(app) except AccessDenied: affected_by = _("You don't have enough permissions") affects = self._affects(app, affected_by) view = HelperView() view.assign("args", args) view.assign("processes", app.instances) view.assign("application", app) view.assign("package", package) view.assign("affected_by", affected_by) view.assign("affects", affects) view.render() else: print(_("Application called {0} is not running").format(app.name))
def render_interactive(self): helper_controller = HelperController(self.args) filtered = self._restartable_applications(self.applications, self.args).sorted("name") while True: view = InteractiveView() view.assign("applications", filtered) view.assign("args", self.args) view.assign("total_count", len(self.applications)) view.assign("session_count", self.applications.count_type(Applications.TYPES['SESSION'])) view.assign("static_count", self.applications.count_type(Applications.TYPES['STATIC'])) view.render() # If there are only hidden applications (any listed) if view.get("total_count") == view.get("session_count") + view.get("static_count"): break print("\n" + _("Press application number for help or 'q' to quit")) answer = input("--> ") try: if answer == "q": return elif int(answer) <= 0 or int(answer) > len(filtered): raise IndexError helper_controller.print_helper(filtered[int(answer) - 1], self.args) except (SyntaxError, IndexError, ValueError): print(_("Wrong application number")) sys.stdout.write("\n-- " + _("Press <enter> to get list of applications") + " --") input()
def render(self): self.print("* {app_name}".format(app_name=self.args.application.name)) # Package informations if self.args.package: self.print(" Package: {pkg_name}".format( pkg_name=self.args.package.name)) self.print(" Description: {pkg_description}".format( pkg_description=self.args.package.description)) self.print(" Type: {type}".format( type=self.args.application.type.capitalize())) else: self.print( " Package: {app_name} is not provided by any package". format(app_name=self.args.application.name)) # State indent = " State: " i = 0 for process in self.args.processes: self.print( indent + "{app_name} has been started by {user} {time} ago. PID - {pid}" .format(app_name=self.args.application.name, user=process.username(), time=process.str_started_ago, pid=process.pid)) indent = " " i += 1 if i >= 3: self.print(" ...") break # Affected by if self.args.args.verbose > 0: self.print("") self.render_affected_by() # How to restart if self.args.application.helper or self.args.affects: self.print("") self.print(" {title}:".format(title=_('How to restart'))) if not self.args.affected_by: self.print( " {app_name} does not need restarting".format( app_name=self.args.application.name)) elif self.args.affects: self.print(" " + _("It's a part of application called {0}").format( self.args.affects)) else: for helper in self.args.application.helpers: self.print(" {how_to_restart}".format( how_to_restart=helper)) if self.args.application.note: self.print("\n - " + self.args.application.note)
def _helper(app): if app.type == Applications.TYPES["DAEMON"]: return "service {0} restart".format(app.name) elif app.type == Applications.TYPES["STATIC"]: return _("You will have to reboot your computer") elif app.type == Applications.TYPES["SESSION"]: return _("You will have to log out & log in again") return None
def _helper(app): if app["type"] == Applications.TYPES["DAEMON"]: return "service {0} restart".format(app["name"]) elif app["type"] == Applications.TYPES["STATIC"]: return _("static_restart") elif app["type"] == Applications.TYPES["SESSION"]: return _("session_restart") return None
def _helper(app): if app.type == Applications.TYPES["DAEMON"]: if System.init_system() == "systemd" and System.distribution() == "arch": return "systemctl restart {0}".format(app.name) else: return "service {0} restart".format(app.name) elif app.type == Applications.TYPES["STATIC"]: return _("You will have to reboot your computer") elif app.type == Applications.TYPES["SESSION"]: return _("You will have to log out & log in again") return None
def render(self): self.print("* {app_name}".format(app_name=self.args.application.name)) # Package informations if self.args.package: self.print(" Package: {pkg_name}" .format(pkg_name=self.args.package.name)) self.print(" Description: {pkg_description}" .format(pkg_description=self.args.package.description)) self.print(" Type: {type}" .format(type=self.args.application.type.capitalize())) if self.args.application.affected_instances: self.print(" Executable: {executable}".format(executable=self.args.application.affected_instances[0].exe)) else: self.print(" Package: {app_name} is not provided by any package" .format(app_name=self.args.application.name)) # State indent = " State: " i = 0 for process in self.args.processes: self.print(indent + "{app_name} has been started by {user} {time} ago. PID - {pid}".format( app_name=self.args.application.name, user=process.username(), time=process.str_started_ago, pid=process.pid )) indent = " " i += 1 if i >= 3: self.print(" ...") break # Affected by if self.args.args.verbose > 0: self.print("") self.render_affected_by() # How to restart if self.args.application.helper or self.args.affects: self.print("") self.print(" {title}:".format(title=_('How to restart'))) if not self.args.affected_by: self.print(" {app_name} does not need restarting".format(app_name=self.args.application.name)) elif self.args.affects: self.print(" " + _("It's a part of application called {0}").format(self.args.affects)) else: for helper in self.args.application.helpers: self.print(" {how_to_restart}".format(how_to_restart=helper)) if self.args.application.note: self.print("\n - " + self.args.application.note)
def render_affected_by(self): default_level = 2 indent = " " self.print(indent + _("Affected by") + ":") if type(self.args.affected_by) == str: self.print(default_level * indent + self.args.affected_by) return printed_packages = set() for process in self.args.affected_by: indent_level = default_level if process not in self.args.processes: self.print(indent_level * indent + "{0} ({1})".format(process.name(), process.pid)) indent_level += 1 for package in process.packages: if package.name not in printed_packages or indent_level > 2: self.print(indent_level * indent + package.name) printed_packages.add(package.name) if self.args.args.verbose < 2: continue indent_level += 1 for file in package.files: self.print(indent_level * indent + file) indent_level -= 1
def run(): args = parser.parse_args() # If there is something on stdin (that means piped into tracer) stdin_packages = [] if not sys.stdin.isatty(): stdin_packages = sys.stdin.readline().split() # All input packages enchanced by actual time (as modified time) packages = [] for package in args.packages + args.pkgs + stdin_packages: packages.append(Package(package, time.time() if args.now else None)) try: router = Router(args, packages) return router.dispatch() except (UnsupportedDistribution, PathNotFound, LockedDatabase) as ex: ex.print() exit(1) except DatabasePermissions as ex: ex.print() print(_("You will probably need to run tracer as root")) exit(1) except (KeyboardInterrupt, EOFError): print("")
def message(self): return _( "You are running unsupported linux distribution\n" "\n" "Please visit https://github.com/FrostyX/tracer/issues\n" "and create new issue called 'Unknown or unsupported linux distribution: {0} (v{1})' if there isn't such.\n" "\n" "Don't you have an GitHub account? Please report this issue on [email protected]")
def render(self): if not self.args.args.quiet and (self.args.session_count > 0 or self.args.static_count > 0): if self.args.session_count + self.args.static_count == self.args.total_count: self.print(_("There are:")) else: self.print(_("Additionally to those process above, there are:")) if self.args.session_count > 0: self.print(" - " + \ _("{0} processes requiring restart of your session (i.e. Logging out & Logging in again)")\ .format(self.args.session_count) ) if self.args.static_count > 0: self.print(" - " + _("{0} processes requiring reboot").format(self.args.static_count))
def trace_affected(self, user=None): """ Returns collection of applications which uses some files that have been modified @TODO This function should be hardly optimized """ memory = self._memory(user) packages = self._modified_packages() affected = {} found = [] for package in packages.unique_newest(): for file in self._PACKAGE_MANAGER.package_files(package.name): file = FilenameCleaner.strip(file) if not file in memory: continue for p in memory[file]: if p.pid in found: continue try: if p.create_time() <= package.modified: found.append(p.pid) p = self._apply_rules(p) a = self._applications.find(p.name()) if not a.ignore: if a.name not in affected: if self._erased and not self._PACKAGE_MANAGER.provided_by( a.name): a.type = Applications.TYPES["ERASED"] affected[a.name] = AffectedApplication( a._attributes) affected[ a. name].affected_instances = AffectedProcessesCollection( ) self._call_hook(affected[a.name]) affected[a.name].affected_instances.append(p) except NoSuchProcess: pass if self._has_updated_kernel( ) and not self._applications.find('kernel').ignore: # Add fake AffectedApplication affected['kernel'] = AffectedApplication({ "name": "kernel", "type": Applications.TYPES["STATIC"], "helper": _("You will have to reboot your computer") }) return ApplicationsCollection(affected.values())
def render(self): if not self.args.args.quiet and (self.args.session_count > 0 or self.args.static_count > 0): if self.args.session_count + self.args.static_count == self.args.total_count: self.print(_("There are:")) else: self.print( _("Additionally to those process above, there are:")) if self.args.session_count > 0: self.print(" - " + \ _("{0} processes requiring restart of your session (i.e. Logging out & Logging in again)")\ .format(self.args.session_count) ) if self.args.static_count > 0: self.print(" - " + _("{0} processes requiring reboot").format( self.args.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 = app['helper'] if app['helper'] else _("not_known_restart") 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)
def _print_note_for_hidden(total_count, session_count, static_count): if not args.quiet and (session_count > 0 or static_count > 0): if session_count + static_count != total_count: print "" print _("note_unlisted_apps") if session_count > 0: print _("requiring_session").format(session_count) if static_count > 0: print _("requiring_reboot").format(static_count)
def trace_affected(self, user=None): """ Returns collection of applications which uses some files that have been modified @TODO This function should be hardly optimized """ memory = self._memory(user) packages = self._modified_packages() affected = {} found = [] for package in packages.unique_newest(): for file in self._PACKAGE_MANAGER.package_files(package.name): file = FilenameCleaner.strip(file) if not file in memory: continue for p in memory[file]: if p.pid in found: continue try: if p.create_time() <= package.modified: found.append(p.pid) p = self._apply_rules(p) a = self._applications.find(p.name()) if not a.ignore: if a.name not in affected: if self._erased and not self._PACKAGE_MANAGER.provided_by(a.name): a.type = Applications.TYPES["ERASED"] affected[a.name] = AffectedApplication(a._attributes) affected[a.name].affected_instances = AffectedProcessesCollection() self._call_hook(affected[a.name]) affected[a.name].affected_instances.append(p) except NoSuchProcess: pass if self._has_updated_kernel() and not self._applications.find('kernel').ignore: # Add fake AffectedApplication affected['kernel'] = AffectedApplication({"name": "kernel", "type": Applications.TYPES["STATIC"], "helper": _("You will have to reboot your computer")}) return ApplicationsCollection(affected.values())
def render(self): if self.args.applications: print(_("You should restart:")) i = 1 digits = len(str(len(self.args.applications))) for application in self.args.applications: n = "[{0}]".format(i).ljust(digits + 2) print("{} {}".format(n, application.name)) i += 1 if not self.args.args.all: if self.args.applications and (self.args.session_count or self.args.static_count): print("") view = NoteForHiddenView() view.assign("args", self.args.args) view.assign("total_count", self.args.total_count) view.assign("session_count", self.args.session_count) view.assign("static_count", self.args.static_count) view.render()
def message(self): return _("Package database is locked by another process")
def message(self): return _("path_not_found") def __init__(self, name):
def message(self): return _("unsupported_distro") def __init__(self, distro):
def message(self): return _( "Problem occurred - neither one of {0} paths exists\n" "Please contact maintainer of tracer package in your distribution." )
def message(self): return _("You can't open package database due to insufficient permissions")
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 args.version: print __version__ sys.exit() if os.getuid() != 0: print _("root_only") sys.exit(); main()
def render(self): def with_helpers_content(): content = "" types = [Applications.TYPES["SESSION"], Applications.TYPES["STATIC"], Applications.TYPES["ERASED"]] applications = self.args.applications.with_helpers().exclude_types(types).sorted("helper") for application in applications: helpers = "; ".join(application.helpers) if application.helper_contains_formating and not application.helper_contains_name: helpers += " # {}".format(application.name) content += " " + helpers + "\n" return content def without_helpers_content(): content = "" apps = self.args.applications.exclude_types(Applications.TYPES["ERASED"]).without_helpers().sorted("name") for application in apps: content += " " + application.name + "\n" return content def erased_content(): content = "" for application in self.args.applications.filter_types([Applications.TYPES["ERASED"]]).sorted("name"): content += " " + application.name + "\n" return content def unrestartable_content(app_type): content = "" applications = self.args.applications.with_helpers().filter_types([app_type]).sorted("name") for application in applications: content += " " + application.name + "\n" return content def note_content(): content = StringIO() view = NoteForHiddenView(content) view.assign("args", self.args.args) view.assign("total_count", len(self.args.applications)) view.assign("session_count", self.args.applications.count_type(Applications.TYPES["SESSION"])) view.assign("static_count", self.args.applications.count_type(Applications.TYPES["STATIC"])) view.render() return content.getvalue() if version_info.major >= 3 else content.getvalue().decode("utf8") blocks = [ {"title": " * " + _("Some applications using:"), "content": with_helpers_content()}, {"title": " * " + _("These applications manually:"), "content": without_helpers_content()}, {"title": " * " + _("Uninstalled applications:"), "content": erased_content()}, ] if self.args.args.all: blocks.append({ "title": " * " + _("These applications restarting your session:"), "content": unrestartable_content(Applications.TYPES["SESSION"]) }) blocks.append({ "title": " * " + _("These applications rebooting your computer:"), "content": unrestartable_content(Applications.TYPES["STATIC"]) }) else: blocks.append({"content": note_content()}) view = BlocksView(self.out) view.assign("blocks", blocks) if view.has_content(): self.print(_("You should restart:")) view.render()
def message(self): return _( "You can't open package database due to insufficient permissions")