我正在使用paramiko设置将执行测试的远程桌面,并且我创建了一个小模块,该模块使用paramiko的sftp实现传输必要的文件。这是我的代码的相关部分:
class MacSSHAgent(paramiko.SSHClient):
def __init__(self, hostname: str, username: str, password: str, workspace: pathlib.Path = None):
super(MacSSHAgent, self).__init__()
self._host = hostname
self._user = username
self._password = password
self._workspace = workspace
self._sftp = None
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
self.logger.addHandler(handler)
return
def __enter__(self):
self.open()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
was_transport_active = self.get_transport().is_active()
self.close()
if exc_type is RebootException:
if was_transport_active:
self.logger.warning(f"Failed to reboot the host '{self._host}'!")
else:
self.logger.info(f"The host '{self._host}' is rebooting...")
return True
def open(self):
self.logger.info(f"Connecting to host '{self._host}' with user '{self._user}' via ssh...")
self.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.connect(hostname=self._host, username=self._user, password=self._password)
self._sftp = self.open_sftp()
self.logger.info(f"Changing directory on host '{self._host}' to {self._workspace}")
self._sftp.chdir(str(self._workspace))
return
@handle_ssh_commands(log_output=True, raise_exception=RebootException)
def reboot(self):
return self.exec_command(f"echo {self._password} | sudo -S shutdown -r now\n")
def transfer_file(self, path: pathlib.Path):
dir_content = self._sftp.listdir()
if path.exists() and path.name not in dir_content and self._sftp.getcwd() == str(self._workspace):
self.logger.info(f"Transferring file '{path.name}' to host '{self._host}'...")
self.logger.info(f"File size: {path.stat().st_size // 1024}KB")
self._sftp.put(path.absolute(), path.name)
self.logger.info(f"File '{path.name}' transferred to host '{self._host}' successfully!")
elif not path.exists():
self.logger.warning(f"File '{path.name}' doesn't exist locally!")
elif path.name in dir_content:
self.logger.warning(f"File '{path.name}' already exists on host '{self._host}'!")
return
def close(self):
self._sftp.close()
super(MacSSHAgent, self).close()
return
@click.command()
@click.argument("ips", nargs=-1, required=True, type=IpAddressType())
@click.option("-u", "--user", required=True, type=click.STRING, help="Login username on the host(s)")
@click.option("-pwd", "--password", required=True, type=click.STRING, help="Password on the host(s)")
@click.option("-ws", "--workspace", type=PathType(file_okay=False, unix_style=True), help="Workspace directory on the host(s), user directory if not specified")
@click.option("-td", "--transfer_dir", default="mac_files", type=PathType(exists=True, file_okay=False), help="Directory which contains the necessary files for transfer")
@click.option("-r", "--reboot", is_flag=True, help="Use this flag to reboot the host(s)")
@click.option("-tf", "--transfer_files", is_flag=True, help="Use this flag to transfer files to the host(s)")
def start_mac_ssh_agent(ips: Tuple[str], user: str, password: str, workspace: pathlib.Path,
transfer_dir: pathlib.Path, reboot: bool, transfer_files: bool):
"""
Reboot or upload necessary files to the Mac computers with specified IP addresses.
IPS - one or more IP address for the host Mac computers
"""
workspace = workspace if workspace else pathlib.PurePosixPath(f"/Users/{user}")
for ip in ips:
with MacSSHAgent(ip, user, password, workspace) as mac_ssh_agent:
if transfer_files:
for file_path in pathlib.Path(transfer_dir).glob("*"):
mac_ssh_agent.transfer_file(file_path)
if reboot:
mac_ssh_agent.reboot()
return
if __name__ == '__main__':
start_mac_ssh_agent()
我正在这样启动脚本:
setup.py -u test -pwd 1234 -td mac_files -tf 192.168.1.1 192.168.1.2 192.168.1.3
输出看起来像这样:
2019-12-10 16:13:56,146 - INFO - Connecting to host '192.168.1.1' with user 'test' via ssh...
2019-12-10 16:13:56,771 - INFO - Changing directory on host '192.168.1.71' to /Users/test
2019-12-10 16:13:56,936 - WARNING - File 'clean.sh' already exists on host '192.168.1.71'!
2019-12-10 16:13:57,042 - WARNING - File 'Test.jpg' already exists on host '192.168.1.71'!
2019-12-10 16:13:57,150 - WARNING - File 'TestBig.pdf' already exists on host '192.168.1.71'!
2019-12-10 16:13:57,152 - INFO - Connecting to host '192.168.1.2' with user 'test' via ssh...
2019-12-10 16:13:57,152 - INFO - Connecting to host '192.168.1.2' with user 'test' via ssh...
2019-12-10 16:13:57,781 - INFO - Changing directory on host '192.168.1.2' to /Users/test
2019-12-10 16:13:57,781 - INFO - Changing directory on host '192.168.1.2' to /Users/test
2019-12-10 16:13:57,943 - WARNING - File 'clean.sh' already exists on host '192.168.1.2'!
2019-12-10 16:13:57,943 - WARNING - File 'clean.sh' already exists on host '192.168.1.2'!
2019-12-10 16:13:58,052 - WARNING - File 'Test.jpg' already exists on host '192.168.1.2'!
2019-12-10 16:13:58,052 - WARNING - File 'Test.jpg' already exists on host '192.168.1.2'!
2019-12-10 16:13:58,158 - WARNING - File 'TestBig.pdf' already exists on host '192.168.1.2'!
2019-12-10 16:13:58,158 - WARNING - File 'TestBig.pdf' already exists on host '192.168.1.2'!
2019-12-10 16:13:58,158 - INFO - Connecting to host '192.168.1.3' with user 'test' via ssh...
2019-12-10 16:13:58,158 - INFO - Connecting to host '192.168.1.3' with user 'test' via ssh...
2019-12-10 16:13:58,158 - INFO - Connecting to host '192.168.1.3' with user 'test' via ssh...
2019-12-10 16:13:58,735 - INFO - Changing directory on host '192.168.1.3' to /Users/test
2019-12-10 16:13:58,735 - INFO - Changing directory on host '192.168.1.3' to /Users/test
2019-12-10 16:13:58,735 - INFO - Changing directory on host '192.168.1.3' to /Users/test
2019-12-10 16:13:58,903 - WARNING - File 'clean.sh' already exists on host '192.168.1.3'!
2019-12-10 16:13:58,903 - WARNING - File 'clean.sh' already exists on host '192.168.1.3'!
2019-12-10 16:13:58,903 - WARNING - File 'clean.sh' already exists on host '192.168.1.3'!
2019-12-10 16:13:59,008 - WARNING - File 'Test.jpg' already exists on host '192.168.1.3'!
2019-12-10 16:13:59,008 - WARNING - File 'Test.jpg' already exists on host '192.168.1.3'!
2019-12-10 16:13:59,008 - WARNING - File 'Test.jpg' already exists on host '192.168.1.3'!
2019-12-10 16:13:59,116 - WARNING - File 'TestBig.pdf' already exists on host '192.168.1.3'!
2019-12-10 16:13:59,116 - WARNING - File 'TestBig.pdf' already exists on host '192.168.1.3'!
2019-12-10 16:13:59,116 - WARNING - File 'TestBig.pdf' already exists on host '192.168.1.3'!
如您所见,由于某些原因,日志成倍增加,但时间戳看起来不错。为什么?
答案 0 :(得分:2)
您正在__init__
中向记录器添加新的处理程序,这被多次调用,因为您创建了许多MacSSHAgent对象:
for ip in ips:
with MacSSHAgent(ip, user, password, workspace) as mac_ssh_agent:
我将在全局级别或静态类字段中配置记录器,因为所有对象已经共享同一记录器。 logging.getLogger
以相同名称调用时会返回相同的记录器:
class MacSSHAgent(paramiko.SSHClient):
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
logger.addHandler(handler)
如果您真的想在__init__
中进行配置,请检查logger是否没有处理程序:
if self.logger.handlers