<code># !/usr/bin/env python</code>
<code># coding:utf-8</code>
<code>import</code> <code>paramiko,datetime,os,threading</code>
<code>import</code> <code>pexpect</code>
<code>from</code> <code>os </code><code>import</code> <code>path, walk, makedirs</code>
<code>from</code> <code>argparse </code><code>import</code> <code>ArgumentParser,RawTextHelpFormatter</code>
<code>from</code> <code>stat </code><code>import</code> <code>S_ISDIR</code>
<code>runing </code><code>=</code> <code>True</code>
<code>def</code> <code>get_args():</code>
<code> </code><code>"""執行個體化類,formatter_class參數允許help資訊以自定義的格式顯示"""</code>
<code> </code><code>parser </code><code>=</code> <code>ArgumentParser(description</code><code>=</code><code>"This is a tool for execute command(s) on remote server(s) or get/put file(s) from/to the remote server(s)\nNotice: please always use '/' as path separater!!!"</code><code>,formatter_class </code><code>=</code><code>RawTextHelpFormatter,epilog</code><code>=</code><code>"Notice:\n If any options use more than once,the last one will overwrite the previous"</code><code>)</code>
<code> </code><code># parser.add_argument('-u',metavar='USER',dest='user',help="remote username",required=True)</code>
<code> </code><code># parser.add_argument('-p',metavar='PASSWORD',dest='passwd',help=" user's password")</code>
<code> </code><code># `parser.add_argument('--pkey',nargs='?',metavar='PRIVATE KEY',dest='pkey',help="local private key,if value not followed by this option,the default is: ~/.ssh/id_rsa",default=None,const='%s/.ssh/id_rsa' % path.expanduser('~'))</code>
<code> </code><code># parser.add_argument('--server', metavar='SERVER_INFO_FILE', help="file include the remote server's information\nwith the format of 'name-ip:port',such as 'web1-192.168.1.100:22',one sever one line", required=True)</code>
<code> </code><code>remote_command </code><code>=</code> <code>parser.add_argument_group(</code><code>'remote command'</code><code>,</code><code>'options for running remote command'</code><code>)</code>
<code> </code><code>remote_command.add_argument(</code><code>'--cmd'</code><code>,metavar</code><code>=</code><code>'“COMMAND”'</code><code>,dest</code><code>=</code><code>'cmd'</code><code>,</code><code>help</code><code>=</code><code>"command run on remote server,multiple commands sperate by ';'"</code><code>)</code>
<code> </code><code>sftp </code><code>=</code> <code>parser.add_argument_group(</code><code>'sftp'</code><code>,</code><code>'options for running sftp'</code><code>)</code>
<code> </code><code>sftp.add_argument(</code><code>'--put'</code><code>,metavar</code><code>=</code><code>'',</code><code>help</code><code>=</code><code>"transfer from local to remote"</code><code>,nargs</code><code>=</code><code>2</code><code>)</code>
<code> </code><code>sftp.add_argument(</code><code>'--get'</code><code>,metavar</code><code>=</code><code>'',</code><code>help</code><code>=</code><code>"transfer from remote to local"</code><code>,nargs</code><code>=</code><code>2</code><code>)</code>
<code> </code><code># 全局字典 鍵(add_argument()中的dest):值(使用者輸入)</code>
<code> </code><code># vars将Namespace object轉換成dict object</code>
<code> </code><code>global</code> <code>args</code>
<code> </code><code>args </code><code>=</code> <code>vars</code><code>(parser.parse_args())</code>
<code> </code><code># 判斷 --cmd --put --get 三個參數的唯一性</code>
<code> </code><code># 清除掉args字典中值為None的項.argparse預設給不出現的值指派None</code>
<code> </code><code>print</code> <code>args</code>
<code> </code><code>n </code><code>=</code> <code>0</code>
<code> </code><code>for</code> <code>i </code><code>in</code> <code>(</code><code>'cmd'</code><code>,</code><code>'put'</code><code>,</code><code>'get'</code><code>):</code>
<code> </code><code>if</code> <code>i </code><code>in</code> <code>args:</code>
<code> </code><code>if</code> <code>args[i] </code><code>is</code> <code>None</code><code>:</code>
<code> </code><code>del</code> <code>args[i]</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>n</code><code>+</code><code>=</code><code>1</code>
<code> </code><code>if</code> <code>n > </code><code>1</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>'\n Only one of the "--cmd --put --get" can be used!'</code><code>)</code>
<code> </code><code>exit(</code><code>10</code><code>)</code>
<code>class</code> <code>run_cmd(threading.Thread):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>,hostname</code><code>=</code><code>None</code><code>,password</code><code>=</code><code>None</code><code>,username</code><code>=</code><code>None</code><code>,port</code><code>=</code><code>None</code><code>,echo_cmd</code><code>=</code><code>None</code><code>):</code>
<code> </code><code>threading.Thread.__init__(</code><code>self</code><code>)</code>
<code> </code><code>self</code><code>.hostname</code><code>=</code><code>hostname</code>
<code> </code><code>self</code><code>.password</code><code>=</code><code>password</code>
<code> </code><code>self</code><code>.username</code><code>=</code><code>username</code>
<code> </code><code>self</code><code>.port</code><code>=</code><code>port</code>
<code> </code><code>self</code><code>.echo_cmd</code><code>=</code><code>echo_cmd</code>
<code> </code><code>self</code><code>.thread_stop</code><code>=</code><code>False</code>
<code> </code><code>def</code> <code>run(</code><code>self</code><code>):</code>
<code> </code><code>paramiko.util.log_to_file(</code><code>'paramiko.log'</code><code>)</code>
<code> </code><code>s</code><code>=</code><code>paramiko.SSHClient()</code>
<code> </code><code>s.set_missing_host_key_policy(paramiko.AutoAddPolicy())</code>
<code> </code><code>s.connect(hostname </code><code>=</code> <code>self</code><code>.hostname,username</code><code>=</code><code>self</code><code>.username, password</code><code>=</code><code>self</code><code>.password)</code>
<code> </code><code>stdin,stdout,stderr</code><code>=</code><code>s.exec_command(</code><code>self</code><code>.echo_cmd)</code>
<code> </code><code>print</code> <code>stdout.read()</code>
<code> </code><code>s.close()</code>
<code> </code><code>def</code> <code>stop(</code><code>self</code><code>):</code>
<code> </code><code>self</code><code>.thread_stop</code><code>=</code><code>True</code>
<code>class</code> <code>upload_thread(threading.Thread):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, hostname</code><code>=</code><code>None</code><code>, password</code><code>=</code><code>None</code><code>, username</code><code>=</code><code>None</code><code>, port</code><code>=</code><code>None</code><code>, local_dir</code><code>=</code><code>None</code><code>, remote_dir</code><code>=</code><code>None</code><code>):</code>
<code> </code><code>threading.Thread.__init__(</code><code>self</code><code>)</code>
<code> </code><code>self</code><code>.hostname </code><code>=</code> <code>hostname</code>
<code> </code><code>self</code><code>.port </code><code>=</code> <code>port</code>
<code> </code><code>self</code><code>.username </code><code>=</code> <code>username</code>
<code> </code><code>self</code><code>.password </code><code>=</code> <code>password</code>
<code> </code><code>self</code><code>.local_dir </code><code>=</code> <code>local_dir</code>
<code> </code><code>self</code><code>.remote_dir </code><code>=</code> <code>remote_dir</code>
<code> </code><code>self</code><code>.thread_stop </code><code>=</code> <code>False</code>
<code> </code><code>def</code> <code>run(</code><code>self</code><code>):</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>t </code><code>=</code> <code>paramiko.Transport((</code><code>self</code><code>.hostname, </code><code>self</code><code>.port))</code>
<code> </code><code>t.connect(username</code><code>=</code><code>self</code><code>.username, password</code><code>=</code><code>self</code><code>.password)</code>
<code> </code><code>sftp </code><code>=</code> <code>paramiko.SFTPClient.from_transport(t)</code>
<code> </code><code>print</code> <code>'upload file start %s '</code> <code>%</code> <code>datetime.datetime.now()</code>
<code> </code><code>for</code> <code>root, dirs, files </code><code>in</code> <code>os.walk(</code><code>self</code><code>.local_dir):</code>
<code> </code><code>for</code> <code>filespath </code><code>in</code> <code>files:</code>
<code> </code><code>local_file </code><code>=</code> <code>os.path.join(root, filespath)</code>
<code> </code><code>a </code><code>=</code> <code>local_file.replace(</code><code>self</code><code>.local_dir, </code><code>self</code><code>.remote_dir)</code>
<code> </code><code>remote_file </code><code>=</code> <code>os.path.join(</code><code>self</code><code>.remote_dir, a)</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>sftp.put(local_file, remote_file)</code>
<code> </code><code>except</code> <code>Exception, e:</code>
<code> </code><code>sftp.mkdir(os.path.split(remote_file)[</code><code>0</code><code>])</code>
<code> </code><code>print</code> <code>"upload %s to remote %s"</code> <code>%</code> <code>(local_file, remote_file)</code>
<code> </code><code>for</code> <code>name </code><code>in</code> <code>dirs:</code>
<code> </code><code>local_path </code><code>=</code> <code>os.path.join(root, name)</code>
<code> </code><code>a </code><code>=</code> <code>local_path.replace(</code><code>self</code><code>.local_dir, </code><code>self</code><code>.remote_dir)</code>
<code> </code><code>remote_path </code><code>=</code> <code>os.path.join(</code><code>self</code><code>.remote_dir, a)</code>
<code> </code><code>sftp.mkdir(remote_path)</code>
<code> </code><code>print</code> <code>"mkdir path %s"</code> <code>%</code> <code>remote_path</code>
<code> </code><code>print</code> <code>e</code>
<code> </code><code>print</code> <code>'upload file success %s '</code> <code>%</code> <code>datetime.datetime.now()</code>
<code> </code><code>t.close()</code>
<code> </code><code>except</code> <code>Exception, e:</code>
<code> </code><code>print</code> <code>e</code>
<code> </code><code>def</code> <code>stop(</code><code>self</code><code>):</code>
<code> </code><code>self</code><code>.thread_stop </code><code>=</code> <code>True</code>
<code>'''</code>
<code>class get_thread(threading.Thread):</code>
<code> </code><code>def __init__(self,hostname=None,password=None,username=None,port=None,local_dir=None,remote_dir=None):</code>
<code> </code><code>threading.Thread.__init__(self)</code>
<code> </code><code>self.hostname=hostname</code>
<code> </code><code>self.port=port</code>
<code> </code><code>self.username=username</code>
<code> </code><code>self.password=password</code>
<code> </code><code>self.local_dir=local_dir</code>
<code> </code><code>self.remote_dir=remote_dir</code>
<code> </code><code>self.thread_stop=False</code>
<code> </code><code>def run(self):</code>
<code> </code><code>try:</code>
<code> </code><code>t=paramiko.Transport((self.hostname,self.port))</code>
<code> </code><code>t.connect(username=self.username,password=self.password)</code>
<code> </code><code>sftp=paramiko.SFTPClient.from_transport(t)</code>
<code> </code><code>print 'get file start %s ' % datetime.datetime.now()</code>
<code> </code><code>for root,dirs,files in os.walk(self.remote_dir):</code>
<code> </code><code>for name in dirs:</code>
<code> </code><code>remote_path = os.path.join(root,name)</code>
<code> </code><code>a = remote_path.replace(self.remote_dir,local_dir)</code>
<code> </code><code>local_path = os.path.join(self.local_dir,a)</code>
<code> </code><code>try:</code>
<code> </code><code>sftp.mkdir(local_path)</code>
<code> </code><code>print "mkdir path %s" % local_path</code>
<code> </code><code>except Exception,e:</code>
<code> </code><code>print e</code>
<code> </code><code>for filespath in files:</code>
<code> </code><code>remote_file = os.path.join(root,filespath)</code>
<code> </code><code>a = remote_file.replace(self.remote_dir,self.local_dir)</code>
<code> </code><code>local_file = os.path.join(self.local_dir,a)</code>
<code> </code><code>sftp.get(remote_file,local_file)</code>
<code> </code><code>sftp.mkdir(os.path.split(local_file)[0])</code>
<code> </code><code>print "get %s to remote %s" % (remote_file,local_file)</code>
<code> </code><code>print 'get file success %s ' % datetime.datetime.now()</code>
<code> </code><code>except Exception,e:</code>
<code> </code><code>print e</code>
<code> </code><code>def stop(self):</code>
<code> </code><code>self.thread_stop=True</code>
<code>class</code> <code>get_thread(threading.Thread):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>,hostname</code><code>=</code><code>None</code><code>,password</code><code>=</code><code>None</code><code>,username</code><code>=</code><code>None</code><code>,port</code><code>=</code><code>None</code><code>,local_dir</code><code>=</code><code>None</code><code>,remote_dir</code><code>=</code><code>None</code><code>):</code>
<code> </code><code>self</code><code>.hostname</code><code>=</code><code>hostname</code>
<code> </code><code>self</code><code>.port</code><code>=</code><code>port</code>
<code> </code><code>self</code><code>.username</code><code>=</code><code>username</code>
<code> </code><code>self</code><code>.password</code><code>=</code><code>password</code>
<code> </code><code>self</code><code>.local_dir</code><code>=</code><code>local_dir</code>
<code> </code><code>self</code><code>.remote_dir</code><code>=</code><code>remote_dir</code>
<code> </code><code>self</code><code>.thread_stop</code><code>=</code><code>False</code>
<code> </code><code>def</code> <code>_walk_remote_dir(</code><code>self</code><code>, remote_dir):</code>
<code> </code><code>dirnames </code><code>=</code> <code>[]</code>
<code> </code><code>filenames </code><code>=</code> <code>[]</code>
<code> </code><code>for</code> <code>fd </code><code>in</code> <code>self</code><code>.sftp.listdir_attr(remote_dir):</code>
<code> </code><code>if</code> <code>S_ISDIR(fd.st_mode):</code>
<code> </code><code>dirnames.append(fd.filename)</code>
<code> </code><code>filenames.append(fd.filename)</code>
<code> </code><code>yield</code> <code>remote_dir, dirnames, filenames</code>
<code> </code><code>for</code> <code>dirname </code><code>in</code> <code>dirnames:</code>
<code> </code><code>new_remote_dir </code><code>=</code> <code>os.path.join(remote_dir, dirname)</code>
<code> </code><code>for</code> <code>walk </code><code>in</code> <code>self</code><code>._walk_remote_dir(new_remote_dir):</code>
<code> </code><code>yield</code> <code>walk</code>
<code> </code><code>t</code><code>=</code><code>paramiko.Transport((</code><code>self</code><code>.hostname,</code><code>self</code><code>.port))</code>
<code> </code><code>t.connect(username</code><code>=</code><code>self</code><code>.username,password</code><code>=</code><code>self</code><code>.password)</code>
<code> </code><code>self</code><code>.sftp</code><code>=</code><code>paramiko.SFTPClient.from_transport(t)</code>
<code> </code><code>print</code> <code>'get file start %s '</code> <code>%</code> <code>datetime.datetime.now()</code>
<code> </code><code>st_mode </code><code>=</code> <code>self</code><code>.sftp.stat(</code><code>self</code><code>.remote_dir).st_mode</code>
<code> </code><code>if</code> <code>not</code> <code>S_ISDIR(st_mode):</code>
<code> </code><code>filename </code><code>=</code> <code>os.path.basename(</code><code>self</code><code>.remote_dir)</code>
<code> </code><code>self</code><code>.sftp.get(</code><code>self</code><code>.remote_dir, os.path.join(local_dir, filename))</code>
<code> </code><code>parent, child </code><code>=</code> <code>os.path.split(</code><code>self</code><code>.remote_dir)</code>
<code> </code><code>for</code> <code>remote_dir, dirnames, filenames </code><code>in</code> <code>self</code><code>._walk_remote_dir(</code><code>self</code><code>.remote_dir):</code>
<code> </code><code>remote_dir </code><code>=</code> <code>remote_dir.replace(parent, </code><code>'.'</code><code>)</code>
<code> </code><code>parentc </code><code>=</code> <code>os.path.join(local_dir, remote_dir)</code>
<code> </code><code>if</code> <code>not</code> <code>os.path.exists(parentc):</code>
<code> </code><code>os.makedirs(parentc)</code>
<code> </code><code>for</code> <code>dirname </code><code>in</code> <code>dirnames:</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>os.makedirs(os.path.join(local_dir, remote_dir, dirname))</code>
<code> </code><code>except</code><code>:</code>
<code> </code><code>pass</code>
<code> </code><code>for</code> <code>filename </code><code>in</code> <code>filenames:</code>
<code> </code><code>local_dirpath </code><code>=</code> <code>os.path.join(local_dir, remote_dir, filename)</code>
<code> </code><code>remote_dirpath </code><code>=</code> <code>os.path.join(parent, remote_dir, filename)</code>
<code> </code><code>self</code><code>.sftp.get(remote_dirpath, local_dirpath)</code>
<code> </code><code>print</code> <code>'get file success %s '</code> <code>%</code> <code>datetime.datetime.now()</code>
<code> </code><code>except</code> <code>Exception,e:</code>
<code> </code><code>self</code><code>.thread_stop</code><code>=</code><code>True</code>
<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>:</code>
<code> </code><code>get_args()</code>
<code> </code><code>if</code> <code>'cmd'</code> <code>in</code> <code>args:</code>
<code> </code><code>username </code><code>=</code> <code>'root'</code>
<code> </code><code>password </code><code>=</code> <code>'xx'</code>
<code> </code><code>port </code><code>=</code> <code>22</code>
<code> </code><code>ip </code><code>=</code> <code>'ip1 ip2'</code>
<code> </code><code>host </code><code>=</code> <code>ip.split(</code><code>' '</code><code>)</code>
<code> </code><code>echo_cmd</code><code>=</code><code>args[</code><code>'cmd'</code><code>]</code>
<code> </code><code>for</code> <code>hostname </code><code>in</code> <code>host:</code>
<code> </code><code>cmd_thread </code><code>=</code> <code>run_cmd(hostname, password, username, port, echo_cmd)</code>
<code> </code><code>print</code> <code>hostname</code>
<code> </code><code>cmd_thread.start()</code>
<code> </code><code>cmd_thread.stop()</code>
<code> </code><code>if</code> <code>(cmd_thread.isAlive()):</code>
<code> </code><code>cmd_thread.join()</code>
<code> </code><code>elif</code> <code>'put'</code> <code>in</code> <code>args:</code>
<code> </code><code>hostname </code><code>=</code> <code>'ip1'</code>
<code> </code><code>local_dir</code><code>=</code><code>args[</code><code>'put'</code><code>][</code><code>0</code><code>]</code>
<code> </code><code>remote_dir</code><code>=</code><code>args[</code><code>'put'</code><code>][</code><code>1</code><code>]</code>
<code> </code><code>print</code> <code>local_dir,remote_dir</code>
<code> </code><code>uploadthread </code><code>=</code> <code>upload_thread(hostname, password, username, port, local_dir, remote_dir)</code>
<code> </code><code>uploadthread.start()</code>
<code> </code><code>uploadthread.stop()</code>
<code> </code><code>if</code> <code>(uploadthread.isAlive()):</code>
<code> </code><code>uploadthread.join()</code>
<code> </code><code>elif</code> <code>'get'</code> <code>in</code> <code>args:</code>
<code> </code><code>local_dir </code><code>=</code> <code>args[</code><code>'get'</code><code>][</code><code>0</code><code>]</code>
<code> </code><code>remote_dir </code><code>=</code> <code>args[</code><code>'get'</code><code>][</code><code>1</code><code>]</code>
<code> </code><code>getthread </code><code>=</code> <code>get_thread(hostname, password, username, port, local_dir, remote_dir)</code>
<code> </code><code>getthread.start()</code>
<code> </code><code>getthread.stop()</code>
<code> </code><code>if</code> <code>(getthread.isAlive()):</code>
<code> </code><code>getthread.join()</code>
使用
python test.py --cmd uptime
python test.py --put /home/nginx /home/nginx
python test.py --get /home/nginx /home/nginx
這個get有點問題,local會變成/home/nginx/nginx多了一層。
使用/home/nginx/ /home/nginx/
<code># -*-coding:utf-8-*-</code>
<code>import</code> <code>os,sys</code>
<code>local</code><code>=</code><code>'/home/logs/a/'</code>
<code>remote</code><code>=</code><code>'/opt/src/logs/a/test-dmin/'</code>
<code>#remote='/opt/src/logs/a/test-dmin' 這兩者結果是不一樣的</code>
<code>parent, child </code><code>=</code> <code>os.path.split(remote)</code>
<code>print</code> <code>parent</code>
<code>dirpath</code><code>=</code><code>remote</code>
<code>dirpath </code><code>=</code> <code>dirpath.replace(parent, </code><code>'.'</code><code>)</code>
<code>dirname</code><code>=</code><code>'test/test2'</code>
<code>print</code> <code>local,dirpath,dirname</code>
<code>print</code> <code>os.path.join(local, dirpath, dirname)</code>
<code>or</code>
<code>local_dir</code><code>=</code><code>'/home/nginx'</code>
<code>remote_dir</code><code>=</code><code>'/home/nginx'</code>
<code>dirname</code><code>=</code><code>'test003'</code>
<code>parent, child </code><code>=</code> <code>os.path.split(remote_dir)</code>
<code>remote_dir </code><code>=</code> <code>remote_dir.replace(parent, </code><code>'.'</code><code>)</code>
<code>parentc </code><code>=</code> <code>os.path.join(local_dir, remote_dir)</code>
<code>print</code> <code>parentc</code>
<code>print</code> <code>remote_dir</code>
<code>print</code> <code>os.path.join(local_dir, remote_dir, dirname)</code>
本文轉自 liqius 51CTO部落格,原文連結:http://blog.51cto.com/szgb17/1913581,如需轉載請自行聯系原作者