From c901c22d7142be9f1f648f4882a8da794c8a160b Mon Sep 17 00:00:00 2001 From: Sonic Build Admin Date: Wed, 2 Jul 2025 16:09:19 +0000 Subject: [PATCH] Fix shebang to /usr/bin/python in ansible modules for compatibility ### Description of PR We encountered the following issue when trying to upgrade ansible: `/bin/sh: 1: /usr/bin/env python3: not found` This error occurred when attempting to invoke certain Ansible modules. According to the [Module format and documentation](https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding), image the recommended shebang is: `#!/usr/bin/python` From the logs, we can observe the following behavior: + When the shebang is /usr/bin/env python, Ansible translates it into: ``` 203 1751357337.89274: _low_level_execute_command(): starting 203 1751357337.89277: _low_level_execute_command(): executing: /bin/sh -c ''"'"'/usr/bin/env python'"'"' && sleep 0' ``` + In contrast, when using /usr/bin/python, Ansible attempts a full interpreter discovery: ``` 171 1751357179.48738: _low_level_execute_command(): starting 171 1751357179.48741: _low_level_execute_command(): executing: /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'python3.13'"'"'; command -v '"'"'python3.12'"'"'; command -v '"'"'python3.11'"'"'; command -v '"'"'python3.10'"'"'; command -v '"'"'python3.9'"'"'; command -v '"'"'python3.8'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python3'"'"'; echo ENDFOUND && sleep 0' ``` This indicates that Ansible treats `/usr/bin/env python` literally and does not invoke its interpreter auto-discovery logic, leading to failures on systems without the python symlink. To satisfy the requirements of the latest ansible, we update the shebang lines in all affected modules in advance. Summary: Fixes # (issue) ### Type of change - [ ] Bug fix - [ ] Testbed and Framework(new/improvement) - [ ] New Test case - [ ] Skipped for non-supported platforms - [x] Test case improvement ### Back port request - [ ] 202205 - [ ] 202305 - [ ] 202311 - [ ] 202405 - [ ] 202411 - [ ] 202505 ### Approach #### What is the motivation for this PR? We encountered the following issue when trying to upgrade ansible: `/bin/sh: 1: /usr/bin/env python3: not found` This error occurred when attempting to invoke certain Ansible modules. According to the [Module format and documentation](https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#python-shebang-utf-8-coding), image the recommended shebang is: `#!/usr/bin/python` From the logs, we can observe the following behavior: + When the shebang is /usr/bin/env python, Ansible translates it into: ``` 203 1751357337.89274: _low_level_execute_command(): starting 203 1751357337.89277: _low_level_execute_command(): executing: /bin/sh -c ''"'"'/usr/bin/env python'"'"' && sleep 0' ``` + In contrast, when using /usr/bin/python, Ansible attempts a full interpreter discovery: ``` 171 1751357179.48738: _low_level_execute_command(): starting 171 1751357179.48741: _low_level_execute_command(): executing: /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'python3.13'"'"'; command -v '"'"'python3.12'"'"'; command -v '"'"'python3.11'"'"'; command -v '"'"'python3.10'"'"'; command -v '"'"'python3.9'"'"'; command -v '"'"'python3.8'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python3'"'"'; echo ENDFOUND && sleep 0' ``` This indicates that Ansible treats `/usr/bin/env python` literally and does not invoke its interpreter auto-discovery logic, leading to failures on systems without the python symlink. To satisfy the requirements of the latest ansible, we update the shebang lines in all affected modules in advance. #### How did you do it? To satisfy the requirements of the latest ansible, this PR updates the shebang lines in all affected modules to #!/usr/bin/python. #### How did you verify/test it? We need to make sure that this change won't affect current test firstly -- test by pipeline itself. And then, we need to make sure that this change works in the new version -- test locally. #### Any platform specific information? #### Supported testbed topology if it's a new test case? ### Documentation --- ansible/library/acl_facts.py | 2 +- ansible/library/announce_routes.py | 2 +- ansible/library/config_facts.py | 2 +- ansible/library/conn_graph_facts.py | 2 +- ansible/library/counter_facts.py | 2 +- ansible/library/dut_basic_facts.py | 2 +- ansible/library/exabgp.py | 2 +- ansible/library/fabric_info.py | 2 +- ansible/library/feature_facts.py | 2 +- ansible/library/generate_golden_config_db.py | 2 +- ansible/library/image_facts.py | 2 +- ansible/library/interface_up_down_data_struct_facts.py | 2 +- ansible/library/lldp_facts.py | 2 +- ansible/library/lldpctl_facts.py | 2 +- ansible/library/minigraph_facts.py | 2 +- ansible/library/mux_cable_facts.py | 2 +- ansible/library/port_alias.py | 2 +- ansible/library/ptf_portchannel.py | 2 +- ansible/library/shell_cmds.py | 2 +- ansible/library/test_facts.py | 2 +- ansible/library/testbed_vm_info.py | 2 +- ansible/library/topo_facts.py | 2 +- ansible/library/vlan_config.py | 2 +- ansible/library/vlan_facts.py | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ansible/library/acl_facts.py b/ansible/library/acl_facts.py index a2ed3cd1a5..4e3b5c0575 100644 --- a/ansible/library/acl_facts.py +++ b/ansible/library/acl_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for gathering ACL related facts from SONiC device. # # The "sonic-cfggen" tool is used to output all the running config data from db in JSON format. ACL table information diff --git a/ansible/library/announce_routes.py b/ansible/library/announce_routes.py index 574f25d168..681767b1a9 100644 --- a/ansible/library/announce_routes.py +++ b/ansible/library/announce_routes.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python import math import os diff --git a/ansible/library/config_facts.py b/ansible/library/config_facts.py index 8d8fe87f0b..6a5f722c83 100644 --- a/ansible/library/config_facts.py +++ b/ansible/library/config_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import json import traceback diff --git a/ansible/library/conn_graph_facts.py b/ansible/library/conn_graph_facts.py index 40c65b5f71..1b282e92c1 100755 --- a/ansible/library/conn_graph_facts.py +++ b/ansible/library/conn_graph_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python import csv from ansible.module_utils.basic import AnsibleModule diff --git a/ansible/library/counter_facts.py b/ansible/library/counter_facts.py index 69de5a1d54..1f64aeff50 100755 --- a/ansible/library/counter_facts.py +++ b/ansible/library/counter_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import re diff --git a/ansible/library/dut_basic_facts.py b/ansible/library/dut_basic_facts.py index 7b9cfd7bce..56c73f7f2e 100644 --- a/ansible/library/dut_basic_facts.py +++ b/ansible/library/dut_basic_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for gathering basic facts from DUT of specified testbed. # # Example output: diff --git a/ansible/library/exabgp.py b/ansible/library/exabgp.py index cd13db21ea..c3981b5e9e 100644 --- a/ansible/library/exabgp.py +++ b/ansible/library/exabgp.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import jinja2 diff --git a/ansible/library/fabric_info.py b/ansible/library/fabric_info.py index e948bf9533..7af5578848 100644 --- a/ansible/library/fabric_info.py +++ b/ansible/library/fabric_info.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import ipaddress diff --git a/ansible/library/feature_facts.py b/ansible/library/feature_facts.py index 2a35ca3521..6ace0babec 100644 --- a/ansible/library/feature_facts.py +++ b/ansible/library/feature_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for gathering feature facts from SONiC device. # diff --git a/ansible/library/generate_golden_config_db.py b/ansible/library/generate_golden_config_db.py index 29bc860f15..1169bee04d 100644 --- a/ansible/library/generate_golden_config_db.py +++ b/ansible/library/generate_golden_config_db.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for generate golden_config_db.json # Currently, only enable dhcp_server feature and generated related configuration in MX device diff --git a/ansible/library/image_facts.py b/ansible/library/image_facts.py index b6bcfb132b..f9e9ed554e 100644 --- a/ansible/library/image_facts.py +++ b/ansible/library/image_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for gathering image facts from SONiC device. # # The "sonic_installer list" command can list the images on SONiC device, including: diff --git a/ansible/library/interface_up_down_data_struct_facts.py b/ansible/library/interface_up_down_data_struct_facts.py index 7e390704b5..93bc6345d0 100644 --- a/ansible/library/interface_up_down_data_struct_facts.py +++ b/ansible/library/interface_up_down_data_struct_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule diff --git a/ansible/library/lldp_facts.py b/ansible/library/lldp_facts.py index 339b4335b0..f8590762a9 100644 --- a/ansible/library/lldp_facts.py +++ b/ansible/library/lldp_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python import json from collections import defaultdict diff --git a/ansible/library/lldpctl_facts.py b/ansible/library/lldpctl_facts.py index b1c9f8cdd1..7984ef7e79 100644 --- a/ansible/library/lldpctl_facts.py +++ b/ansible/library/lldpctl_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for gathering lldp facts from SONiC device. # It takes two argument # asic_instance_id :- Used to specify LLDP Instance in Multi-asic platforms diff --git a/ansible/library/minigraph_facts.py b/ansible/library/minigraph_facts.py index 83d75818fe..3ac4f057d8 100644 --- a/ansible/library/minigraph_facts.py +++ b/ansible/library/minigraph_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from __future__ import print_function from ansible.module_utils.basic import AnsibleModule import calendar diff --git a/ansible/library/mux_cable_facts.py b/ansible/library/mux_cable_facts.py index bc4045083b..14d3bc9105 100644 --- a/ansible/library/mux_cable_facts.py +++ b/ansible/library/mux_cable_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python import os.path import sys import traceback diff --git a/ansible/library/port_alias.py b/ansible/library/port_alias.py index 0535d8e5f4..9685432148 100755 --- a/ansible/library/port_alias.py +++ b/ansible/library/port_alias.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import re diff --git a/ansible/library/ptf_portchannel.py b/ansible/library/ptf_portchannel.py index 50c5e1d0e9..27e52dde8c 100644 --- a/ansible/library/ptf_portchannel.py +++ b/ansible/library/ptf_portchannel.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import jinja2 diff --git a/ansible/library/shell_cmds.py b/ansible/library/shell_cmds.py index 23909e9b04..ba33654f1f 100644 --- a/ansible/library/shell_cmds.py +++ b/ansible/library/shell_cmds.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for running multiple commands by /bin/sh on remote device. # # The ansible builtin module "command" and "shell" can run a single command on the remote device and get its output. diff --git a/ansible/library/test_facts.py b/ansible/library/test_facts.py index cecdfb1b37..385f3dcb1e 100644 --- a/ansible/library/test_facts.py +++ b/ansible/library/test_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import sys import traceback diff --git a/ansible/library/testbed_vm_info.py b/ansible/library/testbed_vm_info.py index 3b91e9bfb9..bb96a409c7 100644 --- a/ansible/library/testbed_vm_info.py +++ b/ansible/library/testbed_vm_info.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.multi_servers_utils import MultiServersUtils diff --git a/ansible/library/topo_facts.py b/ansible/library/topo_facts.py index c34b62e9b1..e5071cdab7 100644 --- a/ansible/library/topo_facts.py +++ b/ansible/library/topo_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python import os import traceback import ipaddress diff --git a/ansible/library/vlan_config.py b/ansible/library/vlan_config.py index 1b84383507..e3d49b8d5f 100644 --- a/ansible/library/vlan_config.py +++ b/ansible/library/vlan_config.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python from ansible.module_utils.basic import AnsibleModule import traceback diff --git a/ansible/library/vlan_facts.py b/ansible/library/vlan_facts.py index 5be7448fc2..39d133636a 100644 --- a/ansible/library/vlan_facts.py +++ b/ansible/library/vlan_facts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # This ansible module is for gathering VLAN related facts from SONiC device. from ansible.module_utils.basic import AnsibleModule