Python calling shell commands. What type of shell is started?
It's /bin/sh
on POSIX. See the source code subprocess.py
(quoting Python 2.7 here):
def _execute_child(self, args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines,
startupinfo, creationflags, shell, to_close,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite):
"""Execute program (POSIX version)"""
if isinstance(args, types.StringTypes):
args = [args]
else:
args = list(args)
if shell:
args = ["/bin/sh", "-c"] + args
if executable:
args[0] = executable
[...]
What shell is run?
This is mentioned in the Python subprocess
documentation:
The executable argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the args argument. If shell=True, the executable argument specifies which shell to use. On Unix, the default shell is
/bin/sh
. On Windows, the default shell is specified by theCOMSPEC
environment variable. The only reason you would need to specifyshell=True
on Windows is where the command you wish to execute is actually built in to the shell, eg dir, copy. You don’t need shell=True to run a batch file, nor to run a console-based executable.
/bin/sh
on Linux/MacOSX is typically an alias for bash (or bash-compatible - newer versions of Debian use dash), whereas on Unixes like Solaris, it might be classic Bourne Shell.
For Windows, it's usually cmd
or command.bat
.
Login shell or not via popen
?
I just realized that I haven't answered your 2nd question - but setting shell=True
will spawn a non-login shell (look @AndiDog's source code link, the way the shell is getting forked would create a non-login shell).
Security Implications
Also be aware that using shell=True
, while it allows you to use shell primitives and shortcuts, can also be a security risk, so be sure to check any possible inputs you might use for process spawning.
Warning Executing shell commands that incorporate unsanitized input from an untrusted source makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. For this reason, the use of shell=True is strongly discouraged in cases where the command string is constructed from external input:
>>>
>>> from subprocess import call
>>> filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / #
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
shell=False
disables all shell based features, but does not suffer from this vulnerability; see the Note in the Popen constructor documentation for helpful hints in getting shell=False to work.