2016-01-08 4 views
5

La memoria del server del mio laboratorio (Ubuntu) si riempie costantemente a causa degli utenti che non chiudono mai i vecchi notebook. Mi piacerebbe avere un'idea migliore di quanta memoria abbia preso ogni notebook. Riesco a riassumere l'utilizzo della memoria (approssimativo) per tutti i notebook jupyter gestiti da ciascun utente, ma mi piacerebbe ottenere l'utilizzo totale della memoria di ogni singolo notebook in modo da poter spegnere quei particolari hog della memoria (o dire a un altro utente di chiudere il suo/lei è giù). Ho rapidamente messo insieme il seguente codice per ottenere circa. mem. utilizzo per kernel jupyter, ma non so come associare gli ID del kernel a un particolare notebook.Notebook Jupyter: utilizzo della memoria per ogni 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

non posso correre questo .. a causa di nessun modulo trovato con l'errore 'PackageNotFoundError: pacchetti mancanti nei canali attuali: - pwd' . qualsiasi altra soluzione che non richiede 'pwd'. Sono su Windows Server con anaconda python 2.7. – ihightower

risposta

3

mi sembrava di avere capito una soluzione di lavoro per il mio problema:

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

ho fatto alcuni miglioramenti al sharchaea's script per la portabilità e velocità.

Principalmente, controllare solo le porte su cui sono in esecuzione i notebook, controllare le diverse opzioni del nome host, migliorare la verifica del processo del kernel e controllare ipython o jupyter.

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) 

io probabilmente continuerò a fare aggiornamenti su questo in questo gist

+0

Non riesco a eseguire questo .. a causa di nessun modulo trovato con errore 'PackageNotFoundError: pacchetti mancanti nei canali correnti: - pwd'. qualsiasi altra soluzione che non richiede 'pwd'. Sono su Windows Server con anaconda python 2.7. – ihightower

+0

@ihightower hmmm, dubito che funzionerà su Windows. Sta ottenendo la maggior parte delle informazioni sui processi da proc, che è un modo Unix di archiviare dati sui processi in esecuzione, sui servizi, ecc. Https://stackoverflow.com/questions/5802143/is-there-anything-like-proc- for-windows potrebbe darti un punto di partenza. – aiguofer