Repository: ansible/ansible

Issue:
Running python scripts with command or shell modules ends up adding the cwd into sys.path
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
ansible 2.1.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

Issue was observed when the `-i` flag was used with `sudo_flags`, but only because this caused the current working directory of the remote script to become the user's home directory, which was dirty and contained random files like `subprocess.py`
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

rhel6.6
rhel7.2
##### SUMMARY

<!--- Explain the problem briefly -->

When running a python script remotely via ansible's _command_ or _shell_ modules, the script's current working directory gets added to its `sys.path`. If the current working directory contained python files that name-conflicted with modules the script was trying to import, a crash inevitably happens. In our case, a rogue, out-of-date `subprocess.py` located in the running user's home directory caused the script to crash upon attempting to `import multiprocessing`.

We tracked the issue to commit https://github.com/ansible/ansible/commit/16c1f10e18f6b4701c5114c51c8f7f6f0ceb96d4, where it looks like ansible is removing paths from `$PYTHONPATH` that was previously added by ziploader. If this step results in an empty list of paths, `$PYTHONPATH` will still exist in `os.environ` but will be set to an empty string.

If python encounters `$PYTHONPATH` set in the environment but with an empty value, it will add an empty string to `sys.path`, and as a result the running python script will look in its current working directory for modules to import. Note that when `site.py` is invoked, the paths will be canonicalized, so it will show within the script as a full path to the current working directory instead of merely `''`, unless python is invoked with the `-Ss` flags. This behavior is true for at least python 2.7.5.
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->



Discussion:

Resolving patch:
diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py
--- a/lib/ansible/module_utils/basic.py
+++ b/lib/ansible/module_utils/basic.py
@@ -2031,6 +2031,8 @@ def run_command(self, args, check_rc=False, close_fds=True, executable=None, dat
                         if not x.endswith('/ansible_modlib.zip') \
                         and not x.endswith('/debug_dir')]
             os.environ['PYTHONPATH'] = ':'.join(pypaths)
+            if not os.environ['PYTHONPATH']:
+                del os.environ['PYTHONPATH']
 
         # create a printable version of the command for use
         # in reporting later, which strips out things like


Test patch: