|
Packit Service |
21c75c |
# Copyright (C) 2016 Red Hat, Inc.
|
|
Packit Service |
21c75c |
#
|
|
Packit Service |
21c75c |
# This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
21c75c |
# it under the terms of the GNU General Public License as published by
|
|
Packit Service |
21c75c |
# the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
21c75c |
# (at your option) any later version.
|
|
Packit Service |
21c75c |
#
|
|
Packit Service |
21c75c |
# This program is distributed in the hope that it will be useful,
|
|
Packit Service |
21c75c |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
21c75c |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
21c75c |
# GNU Library General Public License for more details.
|
|
Packit Service |
21c75c |
#
|
|
Packit Service |
21c75c |
# You should have received a copy of the GNU General Public License
|
|
Packit Service |
21c75c |
# along with this program; if not, write to the Free Software
|
|
Packit Service |
21c75c |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
"""Various utility functions, and a utility class."""
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
from __future__ import absolute_import
|
|
Packit Service |
21c75c |
from __future__ import unicode_literals
|
|
Packit Service |
21c75c |
from dnf.cli.format import format_number
|
|
Packit Service |
21c75c |
from dnf.i18n import _
|
|
Packit Service |
21c75c |
import dnf.util
|
|
Packit Service |
21c75c |
import logging
|
|
Packit Service |
21c75c |
import os
|
|
Packit Service |
21c75c |
import time
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
_USER_HZ = os.sysconf(os.sysconf_names['SC_CLK_TCK'])
|
|
Packit Service |
21c75c |
logger = logging.getLogger('dnf')
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def jiffies_to_seconds(jiffies):
|
|
Packit Service |
21c75c |
"""Convert a number of jiffies to seconds. How many jiffies are in a second
|
|
Packit Service |
21c75c |
is system-dependent, e.g. 100 jiffies = 1 second is common.
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
:param jiffies: a number of jiffies
|
|
Packit Service |
21c75c |
:return: the equivalent number of seconds
|
|
Packit Service |
21c75c |
"""
|
|
Packit Service |
21c75c |
return int(jiffies) / _USER_HZ
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def seconds_to_ui_time(seconds):
|
|
Packit Service |
21c75c |
"""Return a human-readable string representation of the length of
|
|
Packit Service |
21c75c |
a time interval given in seconds.
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
:param seconds: the length of the time interval in seconds
|
|
Packit Service |
21c75c |
:return: a human-readable string representation of the length of
|
|
Packit Service |
21c75c |
the time interval
|
|
Packit Service |
21c75c |
"""
|
|
Packit Service |
21c75c |
if seconds >= 60 * 60 * 24:
|
|
Packit Service |
21c75c |
return "%d day(s) %d:%02d:%02d" % (seconds // (60 * 60 * 24),
|
|
Packit Service |
21c75c |
(seconds // (60 * 60)) % 24,
|
|
Packit Service |
21c75c |
(seconds // 60) % 60,
|
|
Packit Service |
21c75c |
seconds % 60)
|
|
Packit Service |
21c75c |
if seconds >= 60 * 60:
|
|
Packit Service |
21c75c |
return "%d:%02d:%02d" % (seconds // (60 * 60), (seconds // 60) % 60,
|
|
Packit Service |
21c75c |
(seconds % 60))
|
|
Packit Service |
21c75c |
return "%02d:%02d" % ((seconds // 60), seconds % 60)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def get_process_info(pid):
|
|
Packit Service |
21c75c |
"""Return info dict about a process."""
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
pid = int(pid)
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
# Maybe true if /proc isn't mounted, or not Linux ... or something.
|
|
Packit Service |
21c75c |
if (not os.path.exists("/proc/%d/status" % pid) or
|
|
Packit Service |
21c75c |
not os.path.exists("/proc/stat") or
|
|
Packit Service |
21c75c |
not os.path.exists("/proc/%d/stat" % pid)):
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
ps = {}
|
|
Packit Service |
21c75c |
with open("/proc/%d/status" % pid) as status_file:
|
|
Packit Service |
21c75c |
for line in status_file:
|
|
Packit Service |
21c75c |
if line[-1] != '\n':
|
|
Packit Service |
21c75c |
continue
|
|
Packit Service |
21c75c |
data = line[:-1].split(':\t', 1)
|
|
Packit Service |
21c75c |
if len(data) < 2:
|
|
Packit Service |
21c75c |
continue
|
|
Packit Service |
21c75c |
data[1] = dnf.util.rtrim(data[1], ' kB')
|
|
Packit Service |
21c75c |
ps[data[0].strip().lower()] = data[1].strip()
|
|
Packit Service |
21c75c |
if 'vmrss' not in ps:
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
if 'vmsize' not in ps:
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
boot_time = None
|
|
Packit Service |
21c75c |
with open("/proc/stat") as stat_file:
|
|
Packit Service |
21c75c |
for line in stat_file:
|
|
Packit Service |
21c75c |
if line.startswith("btime "):
|
|
Packit Service |
21c75c |
boot_time = int(line[len("btime "):-1])
|
|
Packit Service |
21c75c |
break
|
|
Packit Service |
21c75c |
if boot_time is None:
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
with open('/proc/%d/stat' % pid) as stat_file:
|
|
Packit Service |
21c75c |
ps_stat = stat_file.read().split()
|
|
Packit Service |
21c75c |
ps['start_time'] = boot_time + jiffies_to_seconds(ps_stat[21])
|
|
Packit Service |
21c75c |
ps['state'] = {'R' : _('Running'),
|
|
Packit Service |
21c75c |
'S' : _('Sleeping'),
|
|
Packit Service |
21c75c |
'D' : _('Uninterruptible'),
|
|
Packit Service |
21c75c |
'Z' : _('Zombie'),
|
|
Packit Service |
21c75c |
'T' : _('Traced/Stopped')
|
|
Packit Service |
21c75c |
}.get(ps_stat[2], _('Unknown'))
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
return ps
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
def show_lock_owner(pid):
|
|
Packit Service |
21c75c |
"""Output information about process holding a lock."""
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
ps = get_process_info(pid)
|
|
Packit Service |
21c75c |
if not ps:
|
|
Packit Service |
21c75c |
msg = _('Unable to find information about the locking process (PID %d)')
|
|
Packit Service |
21c75c |
logger.critical(msg, pid)
|
|
Packit Service |
21c75c |
return
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
msg = _(' The application with PID %d is: %s') % (pid, ps['name'])
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
logger.critical("%s", msg)
|
|
Packit Service |
21c75c |
logger.critical(_(" Memory : %5s RSS (%5sB VSZ)"),
|
|
Packit Service |
21c75c |
format_number(int(ps['vmrss']) * 1024),
|
|
Packit Service |
21c75c |
format_number(int(ps['vmsize']) * 1024))
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
ago = seconds_to_ui_time(int(time.time()) - ps['start_time'])
|
|
Packit Service |
21c75c |
logger.critical(_(' Started: %s - %s ago'),
|
|
Packit Service |
21c75c |
dnf.util.normalize_time(ps['start_time']), ago)
|
|
Packit Service |
21c75c |
logger.critical(_(' State : %s'), ps['state'])
|
|
Packit Service |
21c75c |
|
|
Packit Service |
21c75c |
return
|