linux - qstat y nombres de trabajo largos
sungridengine bash4 (7)
¿Cómo puedo hacer que qstat
me dé nombres completos de trabajo?
Sé que qstat -r
proporciona información detallada sobre la tarea, pero es demasiado y se incluyen los requisitos de recursos.
La salida qstat -r
es como:
131806 0.25001 tumor_foca ajalali qw 09/29/2014 15:49:41 1 2-100:1
Full jobname: tumor_focality-TCGA-THCA-ratboost_linear_svc
Hard Resources: distribution=wheezy (0.000000)
h_rt=72000 (0.000000)
mem_free=15G (0.000000)
h_vmem=15G (0.000000)
h_stack=256M (0.000000)
Soft Resources:
131807 0.25001 vital_stat ajalali qw 09/29/2014 15:49:41 1 2-100:1
Full jobname: vital_status-TCGA-LGG-ratboost_linear_svc
Hard Resources: distribution=wheezy (0.000000)
h_rt=72000 (0.000000)
mem_free=15G (0.000000)
h_vmem=15G (0.000000)
h_stack=256M (0.000000)
Soft Resources:
En este momento mi única opción es grep
la salida que necesito:
$ qstat -r | grep "Full jobname" -B1
--
131806 0.25001 tumor_foca ajalali qw 09/29/2014 15:49:41 1 2-100:1
Full jobname: tumor_focality-TCGA-THCA-ratboost_linear_svc
--
131807 0.25001 vital_stat ajalali qw 09/29/2014 15:49:41 1 2-100:1
Full jobname: vital_status-TCGA-LGG-ratboost_linear_svc
¿Puedo hacerlo mejor para tener una salida más agradable?
Actualmente estoy escribiendo mi propio contenedor qstat
para obtener un resultado limpio, útil y personalizable.
Aquí está el repositorio github . El proyecto ha crecido demasiado para que el código se pegue en este mensaje.
Viene con un instalador y debería funcionar sin ningún problema con Python 2.7 y 3 (el script de instalación realiza las modificaciones si es necesario). qjobs -h
proporciona ayuda sobre las opciones disponibles. Escribiré una documentación más completa en los próximos días en la wiki de github.
Actualizaré este mensaje tan a menudo como sea posible para mantener el estado actual del proyecto. Por favor, siéntase libre de comentar aquí (o en github) para solicitar características / reportar problemas.
En un futuro próximo, intentaré agregar un modo totalmente interactivo para navegar por la lista de trabajos más fácilmente. Por supuesto, la salida de texto clásica seguirá estando disponible (podría ser útil enviar la salida por correo electrónico, o para una comprobación rápida de los trabajos pendientes / en ejecución).
Ejemplo de salida
El comando qjobs
da:
5599109 short_name r 2015-06-25 10:27:39 queue1
5599110 jobName r 2015-06-25 10:35:39 queue2
5599111 a_long_job_name qw 2015-06-25 10:40:39
5599112 foo qw 2015-06-25 10:40:39
5599113 bar qw 2015-06-25 10:40:39
5599114 baz qw 2015-06-25 10:40:39
5599115 beer qw 2015-06-25 10:40:39
tot: 7
r: 2 qw: 5
Comando qjobs -o
da:
tot: 7
r: 2 qw: 5
El comando qjobs -o inek -t
da ( e
ha transcurrido desde el inicio / tiempo secundario, el formato se puede personalizar utilizando la especificación de formato. Mini-lenguaje de Python; k
es el nombre completo de la cola, con dominio):
5598985 SpongeBob 522:02 (21.75 days) [email protected]
5598987 ping_java 521:47 (21.74 days) [email protected]
5598988 run3.14 521:46 (21.74 days) [email protected]
5598990 strange_job_42 521:42 (21.74 days) [email protected]
5598991 coffee-maker 521:39 (21.74 days) [email protected]
5598992 dumbtask 521:29 (21.73 days) [email protected]
qjobs -i
ofrece una lista completa de los ''elementos'' disponibles. Cada uno de este artículo está disponible como:
- una salida de columna (con
-o ITEMS
); - como criterio para contar el trabajo y produce una salida total, con
-t
(por ejemplo,-ts
para contar por estado como en los dos primeros ejemplos); - como criterio para ordenar el trabajo con
-s
, el valor predeterminado es-s ips
lo que significa que la lista de trabajos está ordenada por ID, luego por prioridad y finalmente por estado antes de imprimirse.
El resultado de qjobs -i
es:
i: job id
p: job priority
n: job name
o: job owner
s: job state
t: job start/submission time
e: elapsed time since start/submission
q: queue name without domain
d: queue domain
k: queue name with domain
r: requested queue(s)
l: number of slots used
Este script funciona bastante bien. Parece que es de Cambridge. http://www.hep.ph.ic.ac.uk/~dbauer/grid/myqstat.py
Para Python 3:
#!/usr/bin/python
import xml.dom.minidom
import os
import sys
import string
f=os.popen(''qstat -u /* -xml -r'')
dom=xml.dom.minidom.parse(f)
jobs=dom.getElementsByTagName(''job_info'')
run=jobs[0]
runjobs=run.getElementsByTagName(''job_list'')
def fakeqstat(joblist):
for r in joblist:
try:
jobname=r.getElementsByTagName(''JB_name'')[0].childNodes[0].data
jobown=r.getElementsByTagName(''JB_owner'')[0].childNodes[0].data
jobstate=r.getElementsByTagName(''state'')[0].childNodes[0].data
jobnum=r.getElementsByTagName(''JB_job_number'')[0].childNodes[0].data
jobtime=''not set''
if(jobstate==''r''):
jobtime=r.getElementsByTagName(''JAT_start_time'')[0].childNodes[0].data
elif(jobstate==''dt''):
jobtime=r.getElementsByTagName(''JAT_start_time'')[0].childNodes[0].data
else:
jobtime=r.getElementsByTagName(''JB_submission_time'')[0].childNodes[0].data
print(jobnum, ''/t'', jobown.ljust(16), ''/t'', jobname.ljust(16),''/t'', jobstate,''/t'',jobtime)
except Exception as e:
print(e)
fakeqstat(runjobs)
Para Python 2:
#!/usr/bin/python
import xml.dom.minidom
import os
import sys
import string
#import re
f=os.popen(''qstat -u /* -xml -r'')
dom=xml.dom.minidom.parse(f)
jobs=dom.getElementsByTagName(''job_info'')
run=jobs[0]
runjobs=run.getElementsByTagName(''job_list'')
def fakeqstat(joblist):
for r in joblist:
jobname=r.getElementsByTagName(''JB_name'')[0].childNodes[0].data
jobown=r.getElementsByTagName(''JB_owner'')[0].childNodes[0].data
jobstate=r.getElementsByTagName(''state'')[0].childNodes[0].data
jobnum=r.getElementsByTagName(''JB_job_number'')[0].childNodes[0].data
jobtime=''not set''
if(jobstate==''r''):
jobtime=r.getElementsByTagName(''JAT_start_time'')[0].childNodes[0].data
elif(jobstate==''dt''):
jobtime=r.getElementsByTagName(''JAT_start_time'')[0].childNodes[0].data
else:
jobtime=r.getElementsByTagName(''JB_submission_time'')[0].childNodes[0].data
print jobnum, ''/t'', jobown.ljust(16), ''/t'', jobname.ljust(16),''/t'', jobstate,''/t'',jobtime
fakeqstat(runjobs)
Esto es un poco desordenado, pero funciona como una solución simple para tener en el historial de comandos. Todas las herramientas estándar. La salida es prácticamente igual a la que se obtiene de una llamada qstat normal, pero no obtendrá los encabezados:
Un trazador de líneas:
qstat -xml | tr ''/n'' '' '' | sed ''s#<job_list[^>]*>#/n#g'' /
| sed ''s#<[^>]*>##g'' | grep " " | column -t
Descripción de los comandos:
Listar trabajos como XML:
qstat -xml
Eliminar todas las nuevas líneas:
tr ''/n'' '' ''
Agregar nueva línea antes de cada entrada de trabajo en la lista:
sed ''s#<job_list[^>]*>#/n#g''
Eliminar todas las cosas XML:
sed ''s#<[^>]*>##g''
Hack para agregar nueva línea al final:
grep " "
Columnizar:
column -t
Ejemplo de salida
351996 0.50502 ProjectA_XXXXXXXXX_XXXX_XXXXXX user123 r 2015-06-25T15:38:41 [email protected] 1
351997 0.50502 ProjectA_XXX_XXXX_XXX user123 r 2015-06-25T15:39:26 [email protected] 1
351998 0.50502 ProjectA_XXXXXXXXXXXXX_XXXX_XXXX user123 r 2015-06-25T15:40:26 [email protected] 1
351999 0.50502 ProjectA_XXXXXXXXXXXXXXXXX_XXXX_XXXX user123 r 2015-06-25T15:42:11 [email protected] 1
352001 0.50502 ProjectA_XXXXXXXXXXXXXXXXXXXXXXX_XXXX_XXXX user123 r 2015-06-25T15:42:11 [email protected] 1
352008 0.50501 runXXXX69 usr1 r 2015-06-25T15:49:04 [email protected] 1
352009 0.50501 runXXXX70 usr1 r 2015-06-25T15:49:04 [email protected] 1
352010 0.50501 runXXXX71 usr1 r 2015-06-25T15:49:04 [email protected] 1
352011 0.50501 runXXXX72 usr1 r 2015-06-25T15:49:04 [email protected] 1
352012 0.50501 runXXXX73 usr1 r 2015-06-25T15:49:04 [email protected] 1
352013 0.50501 runXXXX74 usr1 r 2015-06-25T15:49:04 [email protected] 1
Gracias a JLT por un código simple y agradable. Lo he ampliado un poco para satisfacer mis necesidades y hacer que se vea bien.
Salida de muestra:
Job ID Job Name Owner Status
------ ------------------------------------ ------ ------
201716 AtacSilN100400K mtsige R
201771 IsoOnGrap400K mtsige R
202067 AtacOnSilica400K mtsige R
202100 AtacGrapN100400K mtsige R
202135 AtacOnSilc400K mtsige R
202145 AtacOnGrap400K mtsige R
202152 AtacOnGraphN3360K mtsige R
202161 AtacticSilicaN10 mtsige R
202163 AtacGrapN10 mtsige R
202169 AtacSilcN10 mtsige R
202192 wallpmma07 am110 R
202193 wallpmma03 am110 R
202194 att03wpm_95solps am110 R
202202 AtacticSilicaN3 mtsige R
203260 8test18_trop_2p ico R
203359 parseAll_Bob/Sub951By50/Cyl20A_atom1 oge1 R
203360 parseAll_Bob/Sub951By50/Cyl30A_atom1 oge1 R
203361 parseAll_Bob/Sub951By50/Cyl30A_atom2 oge1 R
Código:
#!/opt/bin/python3
import os
import xml.etree.ElementTree as ET
#Fields
fields=[''Job_Id'',''Job_Name'',''Job_Owner'',''job_state'']
names=[''Job ID'',''Job Name'',''Owner'',''Status'']
#Get job info
f = os.popen(''qstat -x'')
tree = ET.parse(f)
root = tree.getroot()
n_fields=len(fields)
jobs=[[job.find(field).text for field in fields] for job in root]
max_lengths=[len(name) for name in names]
sep='' ''
#Identify max characer length per field
for j in jobs:
for i in range(n_fields):
#Chop off anything after and including ''@'' or ''.'' from all fields
if j[i].find(''@'')>0:
j[i]=j[i][:j[i].find(''@'')]
if j[i].find(''.'')>0:
j[i]=j[i][:j[i].find(''.'')]
if(len(j[i])>max_lengths[i]):
max_lengths[i]=len(j[i])
#Field names
for i in range(n_fields):
print(''{s:^{length}}''.format(s=names[i],length=max_lengths[i]),end=sep)
print()
#Dashes
for i in range(n_fields):
print(''-''*max_lengths[i],end=sep)
print()
#Jobs
for j in jobs:
for i in range(n_fields):
if j[i].find(''@'')>0:
j[i]=j[i][:j[i].find(''@'')]
print(''{s:<{length}}''.format(s=j[i],length=max_lengths[i]),end=sep)
print()
Para mí, el script de Physical Chemist no funcionó, así que escribí un script muy simple utilizando el módulo xml.tree.ElementTree , que considero algo más sencillo que xml.dom.minidom
import os
import xml.etree.ElementTree as ET
f = os.popen(''qstat -x'')
tree = ET.parse(f)
root = tree.getroot()
print "Job_Id walltime state nodes Job_Name"
print "------ -------- ----- --------------- --------------------------"
for job in root:
print job.find(''Job_Id'').text, " ",
print job.find(''resources_used'').find(''walltime'').text, " ",
print job.find(''job_state'').text, " ",
print job.find(''Resource_List'').find(''nodes'').text, " ",
print job.find(''Job_Name'').text
Tal vez una solución más fácil: establezca SGE_LONG_JOB_NAMES en -1, y qstat determinará el tamaño de la columna de nombre:
export SGE_LONG_JOB_NAMES=-1
qstat -u username
Funciona para mi.
¡Aclamaciones!
Una mala solución KISS:
qstat -xml -f -u /* | fgrep JB_name | wc -l