psutil

Форк
0
/
iotop.py 
181 строка · 4.9 Кб
1
#!/usr/bin/env python3
2

3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
4
# Use of this source code is governed by a BSD-style license that can be
5
# found in the LICENSE file.
6

7
"""A clone of iotop (http://guichaz.free.fr/iotop/) showing real time
8
disk I/O statistics.
9

10
It works on Linux only (FreeBSD and macOS are missing support for IO
11
counters).
12
It doesn't work on Windows as curses module is required.
13

14
Example output:
15

16
$ python3 scripts/iotop.py
17
Total DISK READ: 0.00 B/s | Total DISK WRITE: 472.00 K/s
18
PID   USER      DISK READ  DISK WRITE  COMMAND
19
13155 giampao    0.00 B/s  428.00 K/s  /usr/bin/google-chrome-beta
20
3260  giampao    0.00 B/s    0.00 B/s  bash
21
3779  giampao    0.00 B/s    0.00 B/s  gnome-session --session=ubuntu
22
3830  giampao    0.00 B/s    0.00 B/s  /usr/bin/dbus-launch
23
3831  giampao    0.00 B/s    0.00 B/s  //bin/dbus-daemon --fork --print-pid 5
24
3841  giampao    0.00 B/s    0.00 B/s  /usr/lib/at-spi-bus-launcher
25
3845  giampao    0.00 B/s    0.00 B/s  /bin/dbus-daemon
26
3848  giampao    0.00 B/s    0.00 B/s  /usr/lib/at-spi2-core/at-spi2-registryd
27
3862  giampao    0.00 B/s    0.00 B/s  /usr/lib/gnome-settings-daemon
28

29
Author: Giampaolo Rodola' <g.rodola@gmail.com>
30
"""
31

32
import sys
33
import time
34

35

36
try:
37
    import curses
38
except ImportError:
39
    sys.exit('platform not supported')
40

41
import psutil
42
from psutil._common import bytes2human
43

44

45
win = curses.initscr()
46
lineno = 0
47

48

49
def printl(line, highlight=False):
50
    """A thin wrapper around curses's addstr()."""
51
    global lineno
52
    try:
53
        if highlight:
54
            line += " " * (win.getmaxyx()[1] - len(line))
55
            win.addstr(lineno, 0, line, curses.A_REVERSE)
56
        else:
57
            win.addstr(lineno, 0, line, 0)
58
    except curses.error:
59
        lineno = 0
60
        win.refresh()
61
        raise
62
    else:
63
        lineno += 1
64

65

66
def poll(interval):
67
    """Calculate IO usage by comparing IO statistics before and
68
    after the interval.
69
    Return a tuple including all currently running processes
70
    sorted by IO activity and total disks I/O activity.
71
    """
72
    # first get a list of all processes and disk io counters
73
    procs = list(psutil.process_iter())
74
    for p in procs[:]:
75
        try:
76
            p._before = p.io_counters()
77
        except psutil.Error:
78
            procs.remove(p)
79
            continue
80
    disks_before = psutil.disk_io_counters()
81

82
    # sleep some time
83
    time.sleep(interval)
84

85
    # then retrieve the same info again
86
    for p in procs[:]:
87
        with p.oneshot():
88
            try:
89
                p._after = p.io_counters()
90
                p._cmdline = ' '.join(p.cmdline())
91
                if not p._cmdline:
92
                    p._cmdline = p.name()
93
                p._username = p.username()
94
            except (psutil.NoSuchProcess, psutil.ZombieProcess):
95
                procs.remove(p)
96
    disks_after = psutil.disk_io_counters()
97

98
    # finally calculate results by comparing data before and
99
    # after the interval
100
    for p in procs:
101
        p._read_per_sec = p._after.read_bytes - p._before.read_bytes
102
        p._write_per_sec = p._after.write_bytes - p._before.write_bytes
103
        p._total = p._read_per_sec + p._write_per_sec
104

105
    disks_read_per_sec = disks_after.read_bytes - disks_before.read_bytes
106
    disks_write_per_sec = disks_after.write_bytes - disks_before.write_bytes
107

108
    # sort processes by total disk IO so that the more intensive
109
    # ones get listed first
110
    processes = sorted(procs, key=lambda p: p._total, reverse=True)
111

112
    return (processes, disks_read_per_sec, disks_write_per_sec)
113

114

115
def refresh_window(procs, disks_read, disks_write):
116
    """Print results on screen by using curses."""
117
    curses.endwin()
118
    templ = "%-5s %-7s %11s %11s  %s"
119
    win.erase()
120

121
    disks_tot = "Total DISK READ: %s | Total DISK WRITE: %s" % (
122
        bytes2human(disks_read),
123
        bytes2human(disks_write),
124
    )
125
    printl(disks_tot)
126

127
    header = templ % ("PID", "USER", "DISK READ", "DISK WRITE", "COMMAND")
128
    printl(header, highlight=True)
129

130
    for p in procs:
131
        line = templ % (
132
            p.pid,
133
            p._username[:7],
134
            bytes2human(p._read_per_sec),
135
            bytes2human(p._write_per_sec),
136
            p._cmdline,
137
        )
138
        try:
139
            printl(line)
140
        except curses.error:
141
            break
142
    win.refresh()
143

144

145
def setup():
146
    curses.start_color()
147
    curses.use_default_colors()
148
    for i in range(curses.COLORS):
149
        curses.init_pair(i + 1, i, -1)
150
    curses.endwin()
151
    win.nodelay(1)
152

153

154
def tear_down():
155
    win.keypad(0)
156
    curses.nocbreak()
157
    curses.echo()
158
    curses.endwin()
159

160

161
def main():
162
    global lineno
163
    setup()
164
    try:
165
        interval = 0
166
        while True:
167
            if win.getch() == ord('q'):
168
                break
169
            args = poll(interval)
170
            refresh_window(*args)
171
            lineno = 0
172
            interval = 0.5
173
            time.sleep(interval)
174
    except (KeyboardInterrupt, SystemExit):
175
        pass
176
    finally:
177
        tear_down()
178

179

180
if __name__ == '__main__':
181
    main()
182

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.