2016-01-08 41 views
5

Der Speicher auf dem Server meines Labors (Ubuntu) füllt sich ständig, weil die Benutzer nie alte Notebooks herunterfahren. Ich würde gerne eine bessere Vorstellung davon bekommen, wie viel Speicher jedes Notebook aufnimmt. Ich kann die (grobe) Speichernutzung für alle Jupyter-Notebooks zusammenfassen, die von jedem Benutzer ausgeführt werden, aber ich möchte die Gesamtspeicherauslastung jedes einzelnen Notizbuchs abrufen, damit ich diese bestimmten Speicherschweine herunterfahren kann (oder einem anderen Benutzer sagen, sie ist unten). Ich habe schnell den folgenden Code zusammengestellt, um ca. Mem. Verwendung pro Jupyter-Kernel, aber ich weiß nicht, wie Sie die Kernel-IDs einem bestimmten Notebook zuordnen.Jupyter-Notebook: Speicherverbrauch für jedes Notebook

import os 
import pwd 
import pandas as pd 

UID = 1 
EUID = 2 

pids = [pid for pid in os.listdir('/proc') if pid.isdigit()] 

df = [] 
for pid in pids: 
    try: 
     ret = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read() 
    except IOError: # proc has already terminated 
     continue 

    # jupyter notebook processes 
    if len(ret) > 0 and 'share/jupyter/runtime' in ret: 
     process = psutil.Process(int(pid)) 
     mem = process.memory_info()[0] 

     # user name for pid 
     for ln in open('/proc/%d/status' % int(pid)): 
      if ln.startswith('Uid:'): 
       uid = int(ln.split()[UID]) 
       uname = pwd.getpwuid(uid).pw_name 

     # user, pid, memory, proc_desc 
     df.append([uname, pid, mem, ret]) 

df = pd.DataFrame(df) 
df.columns = ['user', 'pid', 'memory', 'proc_desc'] 
df 
+0

machen werde weiter: Pakete in der aktuellen Kanäle fehlt: - pwd' . eine andere Lösung, die 'pwd' nicht benötigt. Ich bin auf Windows-Server mit Anaconda Python 2.7. – ihightower

Antwort

3

Ich schien eine funktionierende Lösung für mein eigenes Problem herausgefunden zu haben:

import os 
import pwd 
import psutil 
import re 
import string 
import json 
import urllib2 
import pandas as pd 

UID = 1 
EUID = 2 
regex = re.compile(r'.+kernel-(.+)\.json') 

pids = [pid for pid in os.listdir('/proc') if pid.isdigit()] 

# memory info from psutil.Process 
df_mem = [] 
for pid in pids: 
    try: 
     ret = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read() 
    except IOError: # proc has already terminated 
     continue 

    # jupyter notebook processes 
    if len(ret) > 0 and 'share/jupyter/runtime' in ret: 
     # kernel 
     kernel_ID = re.sub(regex, r'\1', ret) 
     kernel_ID = filter(lambda x: x in string.printable, kernel_ID) 

     # memory 
     process = psutil.Process(int(pid)) 
     mem = process.memory_info()[0]/float(1e9) 


     # user name for pid 
     for ln in open('/proc/{}/status'.format(int(pid))): 
      if ln.startswith('Uid:'): 
       uid = int(ln.split()[UID]) 
       uname = pwd.getpwuid(uid).pw_name 

     # user, pid, memory, kernel_ID 
     df_mem.append([uname, pid, mem, kernel_ID]) 

df_mem = pd.DataFrame(df_mem) 
df_mem.columns = ['user', 'pid', 'memory_GB', 'kernel_ID'] 


# notebook info from assessing ports 
df_nb = [] 
for port in xrange(5000,30000): 
    sessions = None 
    try: 
     url = 'http://127.0.0.1:{}/api/sessions'.format(port) 
     sessions = json.load(urllib2.urlopen(url)) 
    except urllib2.URLError: 
     sessions = None 

    if sessions: 
     for sess in sessions: 
      kernel_ID = str(sess['kernel']['id']) 
      notebook_path = sess['notebook']['path'] 
      df_nb.append([port, kernel_ID, notebook_path]) 

df_nb = pd.DataFrame(df_nb) 
df_nb.columns = ['port', 'kernel_ID', 'notebook_path'] 


# joining tables 
df = pd.merge(df_nb, df_mem, on=['kernel_ID'], how='inner') 
df.sort(['memory_GB'], ascending=False) 
2

ich einige Verbesserungen sharchaea's script für die Portabilität und Geschwindigkeit gemacht.

Hauptsächlich nur Ports überprüfen, auf denen Notebooks ausgeführt werden, verschiedene Hostnamenoptionen prüfen, den Kernel-Prozess überprüfen und nach ipython oder jupyter suchen.

import os 
import pwd 
import psutil 
import re 
import string 
import json 
import urllib2 
import socket 
import pandas as pd 

UID = 1 

regex = re.compile(r'.+kernel-(.+)\.json') 
port_regex = re.compile(r'port=(\d+)') 

pids = [pid for pid in os.listdir('/proc') if pid.isdigit()] 

# memory info from psutil.Process 
df_mem = [] 
ports = [] 
default_port = 8888 

for pid in pids: 
    try: 
     ret = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read() 
    except IOError: # proc has already terminated 
     continue 

    # jupyter notebook processes 
    if len(ret) > 0 and ('jupyter-notebook' in ret or 'ipython notebook' in ret): 
     port_match = re.search(port_regex, ret) 
     if port_match: 
      port = port_match.group(1) 
      ports.append(int(port)) 
     else: 
      ports.append(default_port) 
      default_port += 1 
    if len(ret) > 0 and ('jupyter' in ret or 'ipython' in ret) and 'kernel' in ret: 
     # kernel 
     kernel_ID = re.sub(regex, r'\1', ret) 
     kernel_ID = filter(lambda x: x in string.printable, kernel_ID) 

     # memory 
     process = psutil.Process(int(pid)) 
     mem = process.memory_info()[0]/float(1e9) 

     # user name for pid 
     for ln in open('/proc/{0}/status'.format(int(pid))): 
      if ln.startswith('Uid:'): 
       uid = int(ln.split()[UID]) 
       uname = pwd.getpwuid(uid).pw_name 

     # user, pid, memory, kernel_ID 
     df_mem.append([uname, pid, mem, kernel_ID]) 

df_mem = pd.DataFrame(df_mem) 
df_mem.columns = ['user', 'pid', 'memory_GB', 'kernel_ID'] 

# notebook info from assessing ports 
hostnames = [socket.gethostname(), '127.0.0.1', 'localhost', '0.0.0.0'] 
df_nb = [] 
kernels = [] 

for port in set(ports): 
    for hostname in set(hostnames): 
     sessions = None 
     try: 
      url = 'http://{0}:{1}/api/sessions'.format(hostname, port) 
      print url 
      sessions = json.load(urllib2.urlopen(url)) 
     except urllib2.URLError: 
      sessions = None 

     if sessions: 
      for sess in sessions: 
       kernel_ID = str(sess['kernel']['id']) 
       if kernel_ID not in kernels: 
        notebook_path = sess['notebook']['path'] 
        df_nb.append([port, kernel_ID, notebook_path]) 
        kernels.append(kernel_ID) 

df_nb = pd.DataFrame(df_nb) 
df_nb.columns = ['port', 'kernel_ID', 'notebook_path'] 

# joining tables 
df = pd.merge(df_nb, df_mem, on=['kernel_ID'], how='inner') 
df = df.sort_values('memory_GB', ascending=False) 

df.to_csv('notebook_mem_usage.csv', index=False) 

ich wahrscheinlich Aktuelles zu diesem an diesem i dies zu keinem Modul mit Fehler `PackageNotFoundError gefunden fällig .. laufen nicht gist

+0

ich kann dies nicht ausführen .. wegen kein Modul gefunden mit Fehler 'PackageNotFoundError: Pakete fehlen in den aktuellen Kanälen: - pwd'. eine andere Lösung, die 'pwd' nicht benötigt. Ich bin auf Windows-Server mit Anaconda Python 2.7. – ihightower

+0

@ihightower hmmm, ich bezweifle, dass dies unter Windows funktioniert. Es erhält die meisten seiner Informationen über die Prozesse von proc, die eine Unix-Möglichkeit zum Speichern von Daten über laufende Prozesse, Dienste, etc. https://stackoverflow.com/questions/5802143/is-there-any-ything-like-proc- For-Windows könnte Ihnen einen Startpunkt geben. – aiguofer