使用Ansible Python API调用Playbook连接Cisco设备报错求助
Ansible Python API调用Playbook失败:找不到ansible-connection文件
我来帮你分析下这个问题,你遇到的核心矛盾是命令行运行playbook正常,但用Python API调用时就报错找不到ansible-connection脚本,这其实是因为Ansible的命令行工具会自动配置好运行环境,而直接用Python API时需要手动补全这些环境配置。
错误原因拆解
报错/usr/bin/python: can't open file 'ansible-connection'本质是:
- network_cli连接插件需要调用
ansible-connection这个辅助脚本建立持久连接; - 当你用Python API直接运行时,系统的
PATH环境变量里没有包含Ansible的bin目录,导致找不到这个脚本; - 另外你代码里设置的
connection='local'和playbook实际使用的network_cli可能存在环境冲突,API初始化时的连接模式没有匹配playbook的需求。
解决方案步骤
1. 把Ansible的bin目录加入PATH
首先用命令行找到ansible-connection的位置:
which ansible-connection
通常路径是/usr/bin/ansible-connection或者/usr/local/bin/ansible-connection。然后在你的Python代码开头添加环境变量配置:
import os # 替换成你实际的ansible-connection所在目录 ansible_bin_path = '/usr/bin' os.environ['PATH'] = f"{ansible_bin_path}:{os.environ.get('PATH', '')}"
2. 修正Options中的connection参数
你当前设置的connection='local'和playbook使用的network_cli不匹配,虽然playbook可能会覆盖这个设置,但API初始化时保持一致能避免环境混乱。修改Options里的connection值:
options = Options( # 其他参数不变,把connection改成network_cli connection='network_cli', # ... 其余参数保持原样 )
3. 明确指定连接插件路径
有时候API无法自动找到Ansible的连接插件目录,需要手动设置环境变量:
os.environ['ANSIBLE_CONNECTION_PLUGINS'] = '/usr/lib/python2.7/dist-packages/ansible/plugins/connection' # 路径根据你的Ansible安装位置调整,比如也可能是/usr/local/lib/python2.7/dist-packages/...
4. 完整修改后的代码示例
整合以上修改后的代码如下:
#!/usr/bin/env python import os import sys from collections import namedtuple from ansible.executor.task_queue_manager import TaskQueueManager from ansible.inventory.manager import InventoryManager from ansible.parsing.dataloader import DataLoader from ansible.playbook.play import Play from ansible.plugins.callback import CallbackBase from ansible.vars.manager import VariableManager from ansible.executor.playbook_executor import PlaybookExecutor from ansible.utils.display import Display # 配置Ansible环境变量 ansible_bin_path = '/usr/bin' os.environ['PATH'] = f"{ansible_bin_path}:{os.environ.get('PATH', '')}" os.environ['ANSIBLE_CONNECTION_PLUGINS'] = '/usr/lib/python2.7/dist-packages/ansible/plugins/connection' display = Display(verbosity=7) loader = DataLoader() inventory = InventoryManager(loader=loader, sources='/etc/ansible/hosts') variable_manager = VariableManager(loader=loader, inventory=inventory) playbook_path = '/etc/ansible/showrun-routers.yml' if not os.path.exists(playbook_path): print '[INFO] The playbook does not exist' sys.exit() Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check','diff']) options = Options( listtags=False, listtasks=False, listhosts=False, syntax=False, connection='network_cli', module_path='/usr/lib/python2.7/dist-packages/ansible', forks=100, remote_user=None, private_key_file=None, ssh_common_args='', ssh_extra_args='', sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, verbosity=7, check=False, diff=False ) variable_manager = VariableManager(loader=loader, inventory=inventory) passwords = {} pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) results = pbex.run()
补充说明
命令行的ansible-playbook之所以正常,是因为它启动时会自动加载Ansible的环境配置脚本,把必要的路径加入PATH和插件搜索路径。而直接用Python API调用时,这些配置不会自动生效,所以需要手动补充。
内容的提问来源于stack exchange,提问作者袙邪写懈屑 小械屑械薪芯胁
相关产品推荐
相关产品推荐

