如何在Azure的Python Azure Function中正常输出paramiko日志
Azure Function 部署后无法输出paramiko日志的解决方法
问题现象
- 本地运行包含paramiko SFTP操作的Python Azure Function时,可正常获取paramiko库的全量日志
- 部署到Azure平台后,paramiko相关日志完全不输出
- 已尝试的配置未生效:
- 代码中手动设置根日志级别为DEBUG、调用
logging.basicConfig()初始化日志 - host.json中开启全量文件日志,默认日志级别设为Debug
- 应用配置中添加
PYTHON_ENABLE_DEBUG_LOGGING = 1参数
- 代码中手动设置根日志级别为DEBUG、调用
现有实现
函数代码
import datetime import logging import azure.functions as func from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient import paramiko def main(mytimer: func.TimerRequest) -> None: utc_timestamp = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc).isoformat() if mytimer.past_due: logging.info('The timer is past due!') logging.Logger.root.level = 10 logging.basicConfig() logging.getLogger("paramiko").setLevel(logging.DEBUG) # 从Key Vault获取SFTP认证所需密钥 credential = DefaultAzureCredential() secret_client = SecretClient(vault_url="InsertVaultURL", credential=credential) secret_name = secret_client.get_secret("InsertSecretUsernameName") secret_pass = secret_client.get_secret("InsertSecretPasswordName") secret_host_key = secret_client.get_secret("InsertSecretHostKeyName") # SFTP服务器地址 host_name = 'InsertFSTPHostAddress' # 建立SFTP连接 ssh = paramiko.SSHClient() ssh.get_host_keys().add(hostname = host_name, keytype='ssh-rsa', key = paramiko.PKey(data = secret_host_key.value.encode('ascii'))) ssh.load_system_host_keys() ssh.connect(hostname = host_name, port = 22, username=secret_name.value, password=secret_pass.value) sftp = ssh.open_sftp() # 执行SFTP操作 # 省略业务逻辑 # 关闭连接 sftp.close() ssh.close()
host.json配置
{ "version": "2.0", "logging": { "fileLoggingMode": "always", "logLevel": { "default": "Debug" } }, "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[2.*, 3.0.0)" } }
根本原因
Azure Functions Python Worker启动时会提前完成日志系统初始化,接管日志收集管道,用户代码中后续调用logging.basicConfig()不会修改已绑定的日志处理器,paramiko库的日志器默认没有绑定Azure Worker的日志处理器,产生的日志无法被平台收集、输出到日志流。
修复步骤
- 删除代码中无效的日志初始化逻辑
移除以下两行代码,避免打断Azure Worker已配置好的日志路由:logging.Logger.root.level = 10 logging.basicConfig() - 手动将paramiko日志路由到Azure日志管道
在函数入口的日志配置区域,添加以下代码,把Azure日志系统的处理器绑定给paramiko日志器:# 配置paramiko日志 paramiko_logger = logging.getLogger("paramiko") paramiko_logger.setLevel(logging.DEBUG) # 复用Azure平台的日志处理器 for handler in logging.getLogger().handlers: paramiko_logger.addHandler(handler) # 关闭日志冒泡,避免重复输出 paramiko_logger.propagate = False - 修正host.json日志配置
不需要把全局默认日志级别设为Debug(会产生大量冗余系统日志),单独为paramiko指定Debug级别即可,修正后的配置如下:{ "version": "2.0", "logging": { "fileLoggingMode": "always", "logLevel": { "default": "Information", "paramiko": "Debug", "Function": "Trace" }, "console": { "isEnabled": true } }, "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[2.*, 3.0.0)" } } - (可选)需要将paramiko日志落盘时使用可写目录
如果需要实现和paramiko.util.log_to_file("paramiko.log")完全一致的文件日志效果,不要直接写入当前工作目录(Azure沙箱下当前目录多为只读,且临时文件会被定期清理),要写入平台开放的日志目录:
生成的日志文件可以在Function的Kudu管理站点的import os # Azure Function可写日志目录 log_file_path = os.path.join(os.environ["HOME"], "LogFiles", "paramiko.log") paramiko.util.log_to_file(log_file_path, level=logging.DEBUG)LogFiles目录下直接下载查看。
验证方法
重新发布函数、触发执行后,在Azure门户Function的「日志流」页面即可看到paramiko输出的SSH握手、认证、SFTP操作全量调试日志。
内容的提问来源于stack exchange,提问作者PythonForAzure3942
相关产品推荐
相关产品推荐

