Ansible执行Python脚本报错:被当作JSON/YAML解析而非执行
问题现象
本地运行Python端口测试脚本可得到预期输出,但通过Ansible远程执行时,Ansible错误地将Python文件识别为JSON/YAML格式的Playbook,抛出解析失败的错误。
错误信息
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)Syntax Error while loading YAML.
did not find expectedThe error appears to be in '/etc/ansible/playbooks/splunk/splunk.py': line 8, column 1, but may
be elsewhere in the file depending on the exact syntax problem.The offending line appears to be:
#Function that gets stored as the splunkDNS variable then used in the first try/except
def get_ip(hostname):
^ here
相关文件内容
1. splunk.yml Playbook
--- - hosts: local become: False - name: Copy local python script copy to remote ansible.builtin.copy: src: /etc/ansible/playbooks/splunk/splunk.py dest: /root/splunk.py - name: Execute Python Script using the raw module ansible.builtin.raw: python3 /root/splunk.py register: result - debug: msg: "{{ result }}"
2. splunk.py 端口测试脚本
#!/bin/python from contextlib import closing import os, subprocess, sys, socket import ipaddress, random, struct #Function that gets stored as the splunkDNS variable then used in the first try/except def get_ip(hostname): return list( i [4] [0] for i in socket.getaddrinfo( hostname, 80 ) if i[0] is socket.AddressFamily.AF_INET and i[1] is socket.SocketKind.SOCK_RAW ) def get_ip_from_subnet(ip_subnet): ips=ipaddress.ip_network(ip_subnet) ip_list=[str(ip) for ip in ips] return ip_list splunkDNS=get_ip('splunk.com') #Uses the function above to get the IP of the splunk-local domain hostname=os.getenv('HOSTNAME') ip_subnet="1.5.1.128/25" ip_list= get_ip_from_subnet(ip_subnet) randIp = ip_list[random.randint(0,len(ip_list))] print("Hostname: " + str(hostname)) #Check DNS resolution try: if '1.5.1.95' in splunkDNS: #If that .95 IP is anywhere in the output of the get_ip function this returns True. print("DNS Resolution to Splunk is working!") else: print("DNS resolution to splunk.com has failed!\nPlease verify that /etc/resolv.conf contains the following entries: ") except Exception as e: print("Something went wrong! - DNS Step") print(e) #Check if the current machine can send traffic on 1.5.1.95:8089 try: def check_socket(host, port): with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: if sock.connect_ex((host, port)) == 0: print("Can send traffic on 1.5.1.95:8089") else: print("Cannot connect to 1.5.1.95:8089!\n\n") splunkPort=check_socket('1.5.1.95', 8089) except Exception as e: print("Something went wrong! - 8089 Traffic Step") print(e) try: print("Testing the IP: "+randIp) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) result = sock.connect_ex((randIp,9997)) if result == 0: print("Port 9997 is open on " + randIp) else: print("Port 9997 is not open on " + randIp) sock.close() except Exception as e: print("Something went wrong! - Random IP Step") print(e)
3. hosts 配置文件
[local] localhost
解决方案
核心问题定位
报错的直接原因是执行Ansible时指定了错误的文件作为Playbook——你大概率误将splunk.py当作Playbook运行(比如执行ansible-playbook splunk.py),而Ansible会强制解析传入的文件为YAML/JSON格式的Playbook,因此触发语法错误。
正确执行步骤
- 确保执行的是Playbook文件
splunk.yml,而非Python脚本:ansible-playbook /etc/ansible/playbooks/splunk/splunk.yml -i hosts - 额外优化建议:
- 使用
ansible.builtin.script模块替代"copy+raw"的组合,一步完成脚本传输与执行,更简洁高效:
修改splunk.yml中的任务:- name: Execute Python Script directly ansible.builtin.script: /etc/ansible/playbooks/splunk/splunk.py register: result - 给Python脚本添加可执行权限:
chmod +x /etc/ansible/playbooks/splunk/splunk.py - 修复脚本中
randIp的越界问题:random.randint(0, len(ip_list))会取到超出列表索引范围的值,修改为:randIp = ip_list[random.randint(0, len(ip_list)-1)]
- 使用
内容的提问来源于stack exchange,提问作者Gabe_H

