1 本地执行Linux指令
import subprocess
def localSsh(command):
print(f"开始在本地服务器上执行指令:{command}")
p = subprocess.Popen([command],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
out = p.stdout.read().decode('utf-8')
# regex = r'time=(.+?)ms'
print(out)
2 远程执行Linux指令
import paramiko
# 远程登陆操作系统
def remoteSsh(sys_ip, username, command, password=''):
try:
# 创建ssh客户端
client = paramiko.SSHClient()
# 第一次ssh远程时会提示输入yes或者no
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
if len(password) == 0:
print('互信方式远程连接')
key_file = paramiko.RSAKey.from_private_key_file("/root/.ssh/id_rsa")
client.connect(sys_ip, 22, username=username, pkey=key_file, timeout=20)
else:
print('密码方式远程连接') # base64.b64decode(password).decode()
client.connect(sys_ip, 22, username=username, password=password, timeout=20)
print(f"开始在远程服务器上执行指令:{command}")
# 执行查询命令
stdin, stdout, stderr = client.exec_command(f"""{command}""", get_pty=True)
# 获取查询命令执c行结果,返回的数据是一个list
result = stdout.read().decode('utf-8')
print(f"{sys_ip}执行结果:", result)
error = stderr.read().decode('utf-8')
if error != "":
print(f"{sys_ip}错误信息:", error)
else:
pass
except Exception as e:
print(e)
finally:
client.close()
# 批量执行同一命令
def batchExecuteRemoteCommand(host_list, command):
import threading
thread_list = []
for ip, username, password in host_list:
thread = threading.Thread(target = remoteSsh, args = (ip,username,password,command))
thread_list.append(thread)#将生成的线程添加到列表里
for t in thread_list:
t.start() #开始执行线程
for t in thread_list:
t.join() #挂起线程,到所有线程结束
3 本地执行scp命令(不需要输入密码)
def scpFileToRemoteNode(username, aim_ip, password, source_file_path, aim_file_path, port=22):
'''
拷贝软件包到远程节点,默认使用root用户22号端口传输
:return: 0 表示执行成功
'''
import pexpect
password_key = '.*assword.*'
command = f'scp {source_file_path} {username}@{aim_ip}:{aim_file_path}'
print("开始在本地服务器上执行指令: ", command)
try:
execute = pexpect.spawn(command)
execute.expect(password_key)
execute.sendline(password)
execute.expect(pexpect.EOF)
print("拷贝文件到远程服务成功")
except:
print("拷贝文件到远程服务器失败")
4 测试代码
下面以一个远程允许Airflow的代码为例:
if __name__ == '__main__':
airflow_server_ip = "10.20.6.66"
airflow_server_username = "root"
airflow_server_password = "123456"
import sys
import os
if len(sys.argv) > 1:
airflow_yml_path = sys.argv[1]
with open(airflow_yml_path) as f:
airflow_dag_yml_first_line = f.readlines()[0].rstrip()
airflow_dag_id = airflow_dag_yml_first_line[0:len(airflow_dag_yml_first_line) - 1]
airflow_py_base_path = os.getcwd() + "/"
airflow_py_path = airflow_py_base_path + "template_" + airflow_dag_id + ".py"
aim_airflow_dag_yml_path = f"/root/airflow/dags/template_{airflow_dag_id}.yml"
aim_airflow_py_path = f"/root/airflow/dags/template_{airflow_dag_id}.py"
print("产生Airflow运行文件")
airflow_run_code = airflow_run_code.replace("sys.argv[1]", aim_airflow_dag_yml_path)
with open (airflow_py_path, 'w') as file_object:
file_object.write(airflow_run_code)
print('清除远程服务器原始配置文件')
server_command = f"rm -rf {aim_airflow_dag_yml_path}; rm -rf {aim_airflow_py_path}"
remoteSsh(sys_ip=airflow_server_ip, username=airflow_server_username, command=server_command, password=airflow_server_password)
print('开始复制Airflow配置文件到远程服务器')
# 使用账号密码远程scp
if len(airflow_server_password) == 0:
scp_command = f"scp {airflow_yml_path} root@{airflow_server_ip}:{aim_airflow_dag_yml_path}; scp {airflow_py_path} root@{airflow_server_ip}:{aim_airflow_py_path}"
localSsh(scp_command)
else:
scpFileToRemoteNode(username=airflow_server_username, aim_ip=airflow_server_ip, password=airflow_server_password, source_file_path=airflow_yml_path, aim_file_path=aim_airflow_dag_yml_path)
scpFileToRemoteNode(username=airflow_server_username, aim_ip=airflow_server_ip, password=airflow_server_password, source_file_path=airflow_py_path, aim_file_path=aim_airflow_py_path)
print('开始连接远程服务器并执行Airflow任务')
server_command = f"python3 {aim_airflow_py_path} && sleep 300s && airflow dags unpause {airflow_dag_id}"
remoteSsh(sys_ip=airflow_server_ip, username=airflow_server_username, command=server_command, password=airflow_server_password)
else:
print('参数不匹配')