tmux-cssh 와 같이 여러 서버에 명령을 내릴 때, 서버에 접속하지 않고 명령을 보내서 실행이 되도록 Fabric 라이브러리를 사용하여 만들었다. 프로그램을 설치하거나, 공통 스토리지의 마운트, 작업을 실행할 때 유용하게 사용할 수 있다. Connection에서 host="root@192.168.0.xx" 로 넣어주면 root로도 명령을 내릴 수 있다.
사용방법은 간단하다. 실행 파일 뒤쪽에 명령어를 넣어주면 하나의 명령어로 인식하기 때문에 띄어쓰기도 가능다. Pipeline ( | )으로 이어지는 명령어는 " " 안에 넣어준다.
$ j4u.py your command
$ j4u.py "cat read.txt | wc -l"
$ cat j4y.py
#! /usr/bin/env python3
from fabric import Connection
import sys
import parmap
def connect_server(ip,cmd):
result=Connection(host="user@192.168.0."+str(ip), connect_kwargs={"password": "PASSWORD"}).run(cmd, hide=True)
msg = "{0.connection.host} {0.stdout}".format(result).rstrip()
return msg
def main(ip,cmd):
try:
msg=connect_server(ip,cmd)
except:
msg=None
#msg='ERROR: 192.168.0.'+str(ip)
return msg
if __name__=='__main__':
cmd=' '.join(sys.argv[1:])
server=range(11,31)
if cmd=='run':
cmd='ps -e|grep python3.6|wc -l'
elif cmd=='pk':
cmd='pkill python3.6'
elif cmd=='cmd':
cmd='ps -C python3.6 -o %cpu,%mem,cmd --sort=-%cpu'
elif cmd=='hdd1':
cmd='df|grep hdd1'
msgs=parmap.map(main,server,cmd,pm_pbar=False,pm_processes=len(server))
msgs=filter(None,msgs)
msg='\n'.join(msgs)
print(msg)
비균등한 작업 수로 명령을 내려야 할 때 사용하는 방법도 있다. 작업 수는 exponentially 증가한다.
#! /usr/bin/env python3
from fabric import Connection
import sys
import parmap
import time
from math import exp
from math import log
import re
def frange(start, stop, numelements):
"""range function for floats"""
incr = (stop - start) / numelements
return (start + x * incr for x in range(numelements))
def exprange(start, stop, numelements):
"""exponential range - each element is a fixed factor bigger than the previous"""
return (exp(x) for x in frange(log(start), log(stop), numelements))
def natural_sort(l):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
return sorted(l, key = alphanum_key)
def connect_server(ip,cmd):
result=Connection(host="user@192.168.0."+str(ip), connect_kwargs={"password": "PASSWORD"}).run(cmd, hide=True)
msg = "{0.connection.host} {0.stdout}".format(result).rstrip()
return msg
def allocation(ip,cmd):
try:
msg=connect_server(ip,cmd)
except:
msg=None
return msg
def main(arng,interval):
front='for i in {'+str(arng[1])+'..'+str(arng[2])+'};'
main='program -i inputFile -pos ${i}'
cmd=front+'do echo \"'+main+'\"; done |parallel -j 1 {}'
msg=allocation(arng[0],cmd)
return msg
if __name__=='__main__':
ini=11
server=range(int(ini),61)
head=rng[0]
totalJob=272
a=[]
cl=len(server)
limit=cl+1
n=0
while len(a) != limit:
a=set(['%.0f' % x for x in exprange(1,totalJob,cl)])
a=['0']+natural_sort(a)+[str(totalJob)]
if len(a) < limit:
cl = cl + 1
elif len(a) > limit:
cl = cl - 1
n+=1
print(n)
arng=[]
for i in range(len(a)-1):
arng.append([rng[i],int(a[i]),int(a[i+1])-1])
print(arng)
start=time.time()
msgs=parmap.map(main,arng,interval,pm_pbar=False,pm_processes=len(rng))
print('\n\033[92mElapsed time :',time.time()-start,'sec.\033[0m\n')
$ job50.py
19
[[11, 0, 0], [12, 1, 1], [13, 2, 2], [14, 3, 3], [15, 4, 4], [16, 5, 5], [17, 6, 6], [18, 7, 7], [19, 8, 8], [20, 9, 9], [21, 10, 10], [22, 11, 11], [23, 12, 12], [24, 13, 13], [25, 14, 14], [26, 15, 15], [27, 16, 17], [28, 18, 18], [29, 19, 20], [30, 21, 22], [31, 23, 24], [32, 25, 26], [33, 27, 28], [34, 29, 31], [35, 32, 34], [36, 35, 37], [37, 38, 40], [38, 41, 43], [39, 44, 47], [40, 48, 51], [41, 52, 56], [42, 57, 61], [43, 62, 66], [44, 67, 72], [45, 73, 78], [46, 79, 85], [47, 86, 92], [48, 93, 100], [49, 101, 109], [50, 110, 118], [51, 119, 129], [52, 130, 140], [53, 141, 152], [54, 153, 165], [55, 166, 179], [56, 180, 195], [57, 196, 211], [58, 212, 230], [59, 231, 249], [60, 250, 271]]
'Tools' 카테고리의 다른 글
VisiData (0) | 2020.11.20 |
---|---|
Find connection (0) | 2020.11.04 |
tmux-cssh (0) | 2020.10.22 |
TabView (0) | 2020.10.08 |
Monitoring jobs (0) | 2020.09.23 |
댓글